diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 000000000..1d346dec1
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,70 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ # The branches below must be a subset of the branches above
+ branches: [ master ]
+ schedule:
+ - cron: '38 10 * * 4'
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'javascript' ]
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
+ # Learn more about CodeQL language support at https://git.io/codeql-language-support
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v1
+ with:
+ languages: ${{ matrix.language }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v1
+
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 https://git.io/JvXDl
+
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
+ # and modify them (or add more) to build your code if your project
+ # uses a compiled language
+
+ #- run: |
+ # make bootstrap
+ # make release
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v1
diff --git a/README.md b/README.md
index 14485b647..04a88d38d 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,8 @@
[![Downloads][downloads-image]][npm-url]
[![Backers on Open Collective](https://opencollective.com/validatorjs/backers/badge.svg)](#backers)
[![Sponsors on Open Collective](https://opencollective.com/validatorjs/sponsors/badge.svg)](#sponsors)
-[![Gitter](https://badges.gitter.im/validatorjs/community.svg)](https://gitter.im/validatorjs/community)
+[![Gitter][gitter-image]][gitter-url]
+[![Disclose a vulnerability][huntr-image]][huntr-url]
A library of string validators and sanitizers.
@@ -94,7 +95,7 @@ Validator | Description
**isAlpha(str [, locale, options])** | check if the string contains only letters (a-zA-Z).
Locale is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fa-IR', 'fi-FI', 'fr-CA', 'fr-FR', 'he', 'hi-IN', 'hu-HU', 'it-IT', 'ku-IQ', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'sl-SI', 'sk-SK', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`) and defaults to `en-US`. Locale list is `validator.isAlphaLocales`. options is an optional object that can be supplied with the following key(s): ignore which can either be a String or RegExp of characters to be ignored e.g. " -" will ignore spaces and -'s.
**isAlphanumeric(str [, locale, options])** | check if the string contains only letters and numbers (a-zA-Z0-9).
Locale is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fa-IR', 'fi-FI', 'fr-CA', 'fr-FR', 'he', 'hi-IN', 'hu-HU', 'it-IT', 'ku-IQ', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'sl-SI', 'sk-SK', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`) and defaults to `en-US`. Locale list is `validator.isAlphanumericLocales`. options is an optional object that can be supplied with the following key(s): ignore which can either be a String or RegExp of characters to be ignored e.g. " -" will ignore spaces and -'s.
**isAscii(str)** | check if the string contains ASCII chars only.
-**isBase32(str)** | check if a string is base32 encoded.
+**isBase32(str [, options])** | check if a string is base32 encoded. `options` is optional and defaults to `{crockford: false}`.
When `crockford` is true it tests the given base32 encoded string using [Crockford's base32 alternative](http://www.crockford.com/base32.html).
**isBase58(str)** | check if a string is base58 encoded.
**isBase64(str [, options])** | check if a string is base64 encoded. options is optional and defaults to `{urlSafe: false}`
when `urlSafe` is true it tests the given base64 encoded string is [url safe](https://base64.guru/standards/base64url)
**isBefore(str [, date])** | check if the string is a date that's before the specified date.
@@ -129,6 +130,7 @@ Validator | Description
**isIPRange(str [, version])** | check if the string is an IP Range (version 4 or 6).
**isISBN(str [, version])** | check if the string is an ISBN (version 10 or 13).
**isISIN(str)** | check if the string is an [ISIN][ISIN] (stock/security identifier).
+**isISO6391(str)** | check if the string is a valid [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) language code.
**isISO8601(str [, options])** | check if the string is a valid [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date.
`options` is an object which defaults to `{ strict: false, strictSeparator: false }`. If `strict` is true, date strings with invalid dates like `2009-02-29` will be invalid. If `strictSeparator` is true, date strings with date and time separated by anything other than a T will be invalid.
**isISO31661Alpha2(str)** | check if the string is a valid [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) officially assigned country code.
**isISO31661Alpha3(str)** | check if the string is a valid [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) officially assigned country code.
@@ -139,14 +141,14 @@ Validator | Description
**isJWT(str)** | check if the string is valid JWT token.
**isLatLong(str [, options])** | check if the string is a valid latitude-longitude coordinate in the format `lat,long` or `lat, long`.
`options` is an object that defaults to `{ checkDMS: false }`. Pass `checkDMS` as `true` to validate DMS(degrees, minutes, and seconds) latitude-longitude format.
**isLength(str [, options])** | check if the string's length falls in a range.
`options` is an object which defaults to `{min:0, max: undefined}`. Note: this function takes into account surrogate pairs.
-**isLicensePlate(str [, locale])** | check if string matches the format of a country's license plate.
(locale is one of `['cs-CZ', 'de-DE', 'de-LI', 'fi-FI', pt-PT', 'sq-AL', 'pt-BR']` or `any`)
+**isLicensePlate(str [, locale])** | check if string matches the format of a country's license plate.
(locale is one of `['cs-CZ', 'de-DE', 'de-LI', 'fi-FI', 'pt-BR', 'pt-PT', 'sq-AL', 'sv-SE']` or `any`)
**isLocale(str)** | check if the string is a locale
**isLowercase(str)** | check if the string is lowercase.
**isMACAddress(str [, options])** | check if the string is a MAC address.
`options` is an object which defaults to `{no_separators: false}`. If `no_separators` is true, the validator will allow MAC addresses without separators. Also, it allows the use of hyphens, spaces or dots e.g '01 02 03 04 05 ab', '01-02-03-04-05-ab' or '0102.0304.05ab'. The options also allow a `eui` property to specify if it needs to be validated against EUI-48 or EUI-64. The accepted values of `eui` are: 48, 64.
**isMagnetURI(str)** | check if the string is a [magnet uri format](https://en.wikipedia.org/wiki/Magnet_URI_scheme).
**isMD5(str)** | check if the string is a MD5 hash.
Please note that you can also use the `isHash(str, 'md5')` function. Keep in mind that MD5 has some collision weaknesses compared to other algorithms (e.g., SHA).
**isMimeType(str)** | check if the string matches to a valid [MIME type](https://en.wikipedia.org/wiki/Media_type) format
-**isMobilePhone(str [, locale [, options]])** | check if the string is a mobile phone number,
(locale is either an array of locales (e.g `['sk-SK', 'sr-RS']`) OR one of `['am-Am', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', ar-JO', 'ar-KW', 'ar-PS', 'ar-SA', 'ar-SY', 'ar-TN', 'az-AZ', 'az-LY', 'az-LB', 'bs-BA', 'be-BY', 'bg-BG', 'bn-BD', 'ca-AD', 'cs-CZ', 'da-DK', 'de-DE', 'de-AT', 'de-CH', 'de-LU', 'dv-MV', 'el-GR', 'en-AU', 'en-BM', 'en-BW', 'en-CA', 'en-GB', 'en-GG', 'en-GH', 'en-GY', 'en-HK', 'en-MO', 'en-IE', 'en-IN', 'en-KE', 'en-KI', 'en-MT', 'en-MU', 'en-NG', 'en-NZ', 'en-PK', 'en-PH', 'en-RW', 'en-SG', 'en-SL', 'en-UG', 'en-US', 'en-TZ', 'en-ZA', 'en-ZM', 'en-ZW', 'es-AR', 'es-BO', 'es-CL', 'es-CO', 'es-CR', 'es-CU', 'es-DO', 'es-HN', 'es-PE', 'es-EC', 'es-ES', 'es-MX', 'es-PA', 'es-PY', 'es-SV', 'es-UY', 'es-VE', 'et-EE', 'fa-IR', 'fi-FI', 'fj-FJ', 'fo-FO', 'fr-BE', 'fr-BF', 'fr-FR', 'fr-GF', 'fr-GP', 'fr-MQ', 'fr-PF', 'fr-RE', 'ga-IE', 'he-IL', 'hu-HU', 'id-ID', 'it-IT', 'it-SM', 'ja-JP', 'ka-GE', 'kk-KZ', 'kl-GL', 'ko-KR', 'lt-LT', 'ms-MY', 'my-MM', 'mz-MZ', nb-NO', 'ne-NP', 'nl-BE', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'pt-AO', 'ro-RO', 'ru-RU', 'si-LK' 'sl-SI', 'sk-SK', 'sq-AL', 'sr-RS', 'sv-SE', 'tg-TJ', 'th-TH', 'tk-TM', 'tr-TR', 'uk-UA', 'uz-UZ', 'vi-VN', 'zh-CN', 'zh-HK', 'zh-MO', 'zh-TW', 'dz-BT']` OR defaults to 'any'. If 'any' or a falsey value is used, function will check if any of the locales match).
`options` is an optional object that can be supplied with the following keys: `strictMode`, if this is set to `true`, the mobile phone number must be supplied with the country code and therefore must start with `+`. Locale list is `validator.isMobilePhoneLocales`.
+**isMobilePhone(str [, locale [, options]])** | check if the string is a mobile phone number,
(locale is either an array of locales (e.g `['sk-SK', 'sr-RS']`) OR one of `['am-Am', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', ar-JO', 'ar-KW', 'ar-PS', 'ar-SA', 'ar-SY', 'ar-TN', 'az-AZ', 'az-LY', 'az-LB', 'bs-BA', 'be-BY', 'bg-BG', 'bn-BD', 'ca-AD', 'cs-CZ', 'da-DK', 'de-DE', 'de-AT', 'de-CH', 'de-LU', 'dv-MV', 'el-GR', 'en-AU', 'en-BM', 'en-BW', 'en-CA', 'en-GB', 'en-GG', 'en-GH', 'en-GY', 'en-HK', 'en-MO', 'en-IE', 'en-IN', 'en-LS', 'en-KE', 'en-KI', 'en-MT', 'en-MU', 'en-NG', 'en-NZ', 'en-PK', 'en-PH', 'en-RW', 'en-SG', 'en-SL', 'en-UG', 'en-US', 'en-TZ', 'en-ZA', 'en-ZM', 'en-ZW', 'es-AR', 'es-BO', 'es-CL', 'es-CO', 'es-CR', 'es-CU', 'es-DO', 'es-HN', 'es-PE', 'es-EC', 'es-ES', 'es-MX', 'es-PA', 'es-PY', 'es-SV', 'es-UY', 'es-VE', 'et-EE', 'fa-IR', 'fi-FI', 'fj-FJ', 'fo-FO', 'fr-BE', 'fr-BF', 'fr-FR', 'fr-GF', 'fr-GP', 'fr-MQ', 'fr-PF', 'fr-RE', 'ga-IE', 'he-IL', 'hu-HU', 'id-ID', 'it-IT', 'it-SM', 'ja-JP', 'ka-GE', 'kk-KZ', 'kl-GL', 'ko-KR', 'lt-LT', 'ms-MY', 'my-MM', 'mz-MZ', nb-NO', 'ne-NP', 'nl-BE', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'pt-AO', 'ro-RO', 'ru-RU', 'si-LK' 'sl-SI', 'sk-SK', 'sq-AL', 'sr-RS', 'sv-SE', 'tg-TJ', 'th-TH', 'tk-TM', 'tr-TR', 'uk-UA', 'uz-UZ', 'vi-VN', 'zh-CN', 'zh-HK', 'zh-MO', 'zh-TW', 'dz-BT']` OR defaults to 'any'. If 'any' or a falsey value is used, function will check if any of the locales match).
`options` is an optional object that can be supplied with the following keys: `strictMode`, if this is set to `true`, the mobile phone number must be supplied with the country code and therefore must start with `+`. Locale list is `validator.isMobilePhoneLocales`.
**isMongoId(str)** | check if the string is a valid hex-encoded representation of a [MongoDB ObjectId][mongoid].
**isMultibyte(str)** | check if the string contains one or more multibyte chars.
**isNumeric(str [, options])** | check if the string contains only numbers.
`options` is an object which defaults to `{no_symbols: false}` it also has locale as an option. If `no_symbols` is true, the validator will reject numeric strings that feature a symbol (e.g. `+`, `-`, or `.`).
`locale` determine the decimal separator and is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fr-FR', 'fr-CA', 'hu-HU', 'it-IT', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'sl-SI', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`.
@@ -161,7 +163,7 @@ Validator | Description
**isUppercase(str)** | check if the string is uppercase.
**isSlug** | Check if the string is of type slug. `Options` allow a single hyphen between string. e.g. [`cn-cn`, `cn-c-c`]
**isStrongPassword(str [, options])** | Check if a password is strong or not. Allows for custom requirements or scoring rules. If `returnScore` is true, then the function returns an integer score for the password rather than a boolean.
Default options:
`{ minLength: 8, minLowercase: 1, minUppercase: 1, minNumbers: 1, minSymbols: 1, returnScore: false, pointsPerUnique: 1, pointsPerRepeat: 0.5, pointsForContainingLower: 10, pointsForContainingUpper: 10, pointsForContainingNumber: 10, pointsForContainingSymbol: 10 }`
-**isTaxID(str, locale)** | Check if the given value is a valid Tax Identification Number. Default locale is `en-US`.
More info about exact TIN support can be found in `src/lib/isTaxID.js`
Supported locales: `[ 'bg-BG', 'cs-CZ', 'de-AT', 'de-DE', 'dk-DK', 'el-CY', 'el-GR', 'en-GB', 'en-IE', 'en-US', 'es-ES', 'et-EE', 'fi-FI', 'fr-BE', 'fr-FR', 'fr-LU', 'hr-HR', 'hu-HU', 'it-IT', 'lb-LU', 'lt-LT', 'lv-LV' 'mt-MT', 'nl-BE', 'nl-NL', 'pl-PL', 'pt-BR', 'pt-PT', 'ro-RO', 'sk-SK', 'sl-SI', 'sv-SE' ]`
+**isTaxID(str, locale)** | Check if the given value is a valid Tax Identification Number. Default locale is `en-US`.
More info about exact TIN support can be found in `src/lib/isTaxID.js`
Supported locales: `[ 'bg-BG', 'cs-CZ', 'de-AT', 'de-DE', 'dk-DK', 'el-CY', 'el-GR', 'en-CA', 'en-GB', 'en-IE', 'en-US', 'es-ES', 'et-EE', 'fi-FI', 'fr-BE', 'fr-CA', 'fr-FR', 'fr-LU', 'hr-HR', 'hu-HU', 'it-IT', 'lb-LU', 'lt-LT', 'lv-LV' 'mt-MT', 'nl-BE', 'nl-NL', 'pl-PL', 'pt-BR', 'pt-PT', 'ro-RO', 'sk-SK', 'sl-SI', 'sv-SE' ]`
**isURL(str [, options])** | check if the string is an URL.
`options` is an object which defaults to `{ protocols: ['http','https','ftp'], require_tld: true, require_protocol: false, require_host: true, require_port: false, require_valid_protocol: true, allow_underscores: false, host_whitelist: false, host_blacklist: false, allow_trailing_dot: false, allow_protocol_relative_urls: false, allow_fragments: true, allow_query_components: true, disallow_auth: false, validate_length: true }`.
require_protocol - if set as true isURL will return false if protocol is not present in the URL.
require_valid_protocol - isURL will check if the URL's protocol is present in the protocols option.
protocols - valid protocols can be modified with this option.
require_host - if set as false isURL will not check if host is present in the URL.
require_port - if set as true isURL will check if port is present in the URL.
allow_protocol_relative_urls - if set as true protocol relative URLs will be allowed.
allow_fragments - if set as false isURL will return false if fragments are present.
allow_query_components - if set as false isURL will return false if query components are present.
validate_length - if set as false isURL will skip string length validation (2083 characters is IE max URL length).
**isUUID(str [, version])** | check if the string is a UUID (version 1, 2, 3, 4 or 5).
**isVariableWidth(str)** | check if the string contains a mixture of full and half-width chars.
@@ -226,6 +228,8 @@ $ npm test
- [chriso](https://github.com/chriso) - **Chris O'Hara** (author)
- [profnandaa](https://github.com/profnandaa) - **Anthony Nandaa**
+- [ezkemboi](https://github.com/ezkemboi) - **Ezrqn Kemboi**
+- [tux-tn](https://github.com/tux-tn) - **Sarhan Aissi**
## Reading
@@ -267,6 +271,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[ci-url]: https://github.com/validatorjs/validator.js/actions?query=workflow%3ACI
[ci-image]: https://github.com/validatorjs/validator.js/workflows/CI/badge.svg?branch=master
+[gitter-url]: https://gitter.im/validatorjs/community
+[gitter-image]: https://badges.gitter.im/validatorjs/community.svg
+
+[huntr-url]: https://huntr.dev/bounties/disclose/?target=https://github.com/validatorjs/validator.js
+[huntr-image]: https://cdn.huntr.dev/huntr_security_badge_mono.svg
+
[amd]: http://requirejs.org/docs/whyamd.html
[bower]: http://bower.io/
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000..72592f135
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,11 @@
+# Security Policy
+
+## Supported Versions
+
+In the case of a confirmed security issue, only the current version of validator is guaranteed to be patched.
+
+## Reporting a Vulnerability
+
+**Please don't disclose security-related issues publicly.**
+
+If you discover a vulnerability within validator, please use [huntr.dev disclosure form](https://huntr.dev/bounties/disclose/?target=https://github.com/validatorjs/validator.js). We will try to validate and respond to reports in a reasonable time. if the issue is confirmed, we will create a security advisory and a patch as soon as possible.
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index b8ad651ee..ec6fe528a 100644
--- a/src/index.js
+++ b/src/index.js
@@ -86,6 +86,7 @@ import isCurrency from './lib/isCurrency';
import isBtcAddress from './lib/isBtcAddress';
+import isISO6391 from './lib/isISO6391';
import isISO8601 from './lib/isISO8601';
import isRFC3339 from './lib/isRFC3339';
import isISO31661Alpha2 from './lib/isISO31661Alpha2';
@@ -195,6 +196,7 @@ const validator = {
isEthereumAddress,
isCurrency,
isBtcAddress,
+ isISO6391,
isISO8601,
isRFC3339,
isISO31661Alpha2,
diff --git a/src/lib/isBase32.js b/src/lib/isBase32.js
index b2e9c8a28..5e2969cbc 100644
--- a/src/lib/isBase32.js
+++ b/src/lib/isBase32.js
@@ -1,9 +1,21 @@
import assertString from './util/assertString';
+import merge from './util/merge';
const base32 = /^[A-Z2-7]+=*$/;
+const crockfordBase32 = /^[A-HJKMNP-TV-Z0-9]+$/;
-export default function isBase32(str) {
+const defaultBase32Options = {
+ crockford: false,
+};
+
+export default function isBase32(str, options) {
assertString(str);
+ options = merge(options, defaultBase32Options);
+
+ if (options.crockford) {
+ return crockfordBase32.test(str);
+ }
+
const len = str.length;
if (len % 8 === 0 && base32.test(str)) {
return true;
diff --git a/src/lib/isDataURI.js b/src/lib/isDataURI.js
index 01e43f70c..966a6f3db 100644
--- a/src/lib/isDataURI.js
+++ b/src/lib/isDataURI.js
@@ -1,6 +1,6 @@
import assertString from './util/assertString';
-const validMediaType = /^[a-z]+\/[a-z0-9\-\+]+$/i;
+const validMediaType = /^[a-z]+\/[a-z0-9\-\+\.]+$/i;
const validAttribute = /^[a-z\-]+=[a-z0-9\-]+$/i;
diff --git a/src/lib/isISO6391.js b/src/lib/isISO6391.js
new file mode 100644
index 000000000..eaa01c5b4
--- /dev/null
+++ b/src/lib/isISO6391.js
@@ -0,0 +1,35 @@
+import assertString from './util/assertString';
+
+const isISO6391Set = new Set([
+ 'aa', 'ab', 'ae', 'af', 'ak', 'am', 'an', 'ar', 'as', 'av', 'ay', 'az', 'az',
+ 'ba', 'be', 'bg', 'bh', 'bi', 'bm', 'bn', 'bo', 'br', 'bs',
+ 'ca', 'ce', 'ch', 'co', 'cr', 'cs', 'cu', 'cv', 'cy',
+ 'da', 'de', 'dv', 'dz',
+ 'ee', 'el', 'en', 'eo', 'es', 'et', 'eu',
+ 'fa', 'ff', 'fi', 'fj', 'fo', 'fr', 'fy',
+ 'ga', 'gd', 'gl', 'gn', 'gu', 'gv',
+ 'ha', 'he', 'hi', 'ho', 'hr', 'ht', 'hu', 'hy', 'hz',
+ 'ia', 'id', 'ie', 'ig', 'ii', 'ik', 'io', 'is', 'it', 'iu',
+ 'ja', 'jv',
+ 'ka', 'kg', 'ki', 'kj', 'kk', 'kl', 'km', 'kn', 'ko', 'kr', 'ks', 'ku', 'kv', 'kw', 'ky',
+ 'la', 'lb', 'lg', 'li', 'ln', 'lo', 'lt', 'lu', 'lv',
+ 'mg', 'mh', 'mi', 'mk', 'ml', 'mn', 'mr', 'ms', 'mt', 'my',
+ 'na', 'nb', 'nd', 'ne', 'ng', 'nl', 'nn', 'no', 'nr', 'nv', 'ny',
+ 'oc', 'oj', 'om', 'or', 'os',
+ 'pa', 'pi', 'pl', 'ps', 'pt',
+ 'qu',
+ 'rm', 'rn', 'ro', 'ru', 'rw',
+ 'sa', 'sc', 'sd', 'se', 'sg', 'si', 'sk', 'sl', 'sm', 'sn', 'so', 'sq', 'sr', 'ss', 'st', 'su', 'sv', 'sw',
+ 'ta', 'te', 'tg', 'th', 'ti', 'tk', 'tl', 'tn', 'to', 'tr', 'ts', 'tt', 'tw', 'ty',
+ 'ug', 'uk', 'ur', 'uz',
+ 've', 'vi', 'vo',
+ 'wa', 'wo',
+ 'xh',
+ 'yi', 'yo',
+ 'za', 'zh', 'zu',
+]);
+
+export default function isISO6391(str) {
+ assertString(str);
+ return isISO6391Set.has(str);
+}
diff --git a/src/lib/isLicensePlate.js b/src/lib/isLicensePlate.js
index d6b27a5ad..668064f13 100644
--- a/src/lib/isLicensePlate.js
+++ b/src/lib/isLicensePlate.js
@@ -13,6 +13,8 @@ const validators = {
/^[A-Z]{2}[- ]?((\d{3}[- ]?(([A-Z]{2})|T))|(R[- ]?\d{3}))$/.test(str),
'pt-BR': str =>
/^[A-Z]{3}[ -]?[0-9][A-Z][0-9]{2}|[A-Z]{3}[ -]?[0-9]{4}$/.test(str),
+ 'sv-SE': str =>
+ /^[A-HJ-PR-UW-Z]{3} ?[\d]{2}[A-HJ-PR-UW-Z1-9]$|(^[A-ZÅÄÖ ]{2,7}$)/.test(str.trim()),
};
export default function isLicensePlate(str, locale) {
diff --git a/src/lib/isMobilePhone.js b/src/lib/isMobilePhone.js
index 575415e27..e19184ba9 100644
--- a/src/lib/isMobilePhone.js
+++ b/src/lib/isMobilePhone.js
@@ -18,7 +18,7 @@ const phones = {
'ar-SA': /^(!?(\+?966)|0)?5\d{8}$/,
'ar-SY': /^(!?(\+?963)|0)?9\d{8}$/,
'ar-TN': /^(\+?216)?[2459]\d{7}$/,
- 'az-AZ': /^(\+994|0)(5[015]|7[07]|99)\d{7}$/,
+ 'az-AZ': /^(\+994|0)(10|5[015]|7[07]|99)\d{7}$/,
'bs-BA': /^((((\+|00)3876)|06))((([0-3]|[5-6])\d{6})|(4\d{7}))$/,
'be-BY': /^(\+?375)?(24|25|29|33|44)\d{7}$/,
'bg-BG': /^(\+?359|0)?8[789]\d{7}$/,
@@ -44,6 +44,7 @@ const phones = {
'en-IN': /^(\+?91|0)?[6789]\d{9}$/,
'en-KE': /^(\+?254|0)(7|1)\d{8}$/,
'en-KI': /^((\+686|686)?)?( )?((6|7)(2|3|8)[0-9]{6})$/,
+ 'en-LS': /^(\+?266)(22|28|57|58|59|27|52)\d{6}$/,
'en-MT': /^(\+?356|0)?(99|79|77|21|27|22|25)[0-9]{6}$/,
'en-MU': /^(\+?230|0)?\d{8}$/,
'en-NA': /^(\+?264|0)(6|8)\d{7}$/,
diff --git a/src/lib/isTaxID.js b/src/lib/isTaxID.js
index ee66ca326..f43c61a15 100644
--- a/src/lib/isTaxID.js
+++ b/src/lib/isTaxID.js
@@ -60,6 +60,36 @@ function bgBgCheck(tin) {
return checksum === digits[9];
}
+/**
+ * Check if an input is a valid Canadian SIN (Social Insurance Number)
+ *
+ * The Social Insurance Number (SIN) is a 9 digit number that
+ * you need to work in Canada or to have access to government programs and benefits.
+ *
+ * https://en.wikipedia.org/wiki/Social_Insurance_Number
+ * https://www.canada.ca/en/employment-social-development/services/sin.html
+ * https://www.codercrunch.com/challenge/819302488/sin-validator
+ *
+ * @param {string} input
+ * @return {boolean}
+ */
+function isCanadianSIN(input) {
+ const digitsArray = input.split('');
+ const even = digitsArray
+ .filter((_, idx) => idx % 2)
+ .map(i => Number(i) * 2)
+ .join('')
+ .split('');
+
+ const total = digitsArray
+ .filter((_, idx) => !(idx % 2))
+ .concat(even)
+ .map(i => Number(i))
+ .reduce((acc, cur) => acc + cur);
+
+ return (total % 10 === 0);
+}
+
/*
* cs-CZ validation function
* (Rodné číslo (RČ), persons only)
@@ -1096,7 +1126,6 @@ function svSeCheck(tin) {
* uppercase and lowercase letters are acceptable.
*/
const taxIdFormat = {
-
'bg-BG': /^\d{10}$/,
'cs-CZ': /^\d{6}\/{0,1}\d{3,4}$/,
'de-AT': /^\d{9}$/,
@@ -1104,6 +1133,7 @@ const taxIdFormat = {
'dk-DK': /^\d{6}-{0,1}\d{4}$/,
'el-CY': /^[09]\d{7}[A-Z]$/,
'el-GR': /^([0-4]|[7-9])\d{8}$/,
+ 'en-CA': /^\d{9}$/,
'en-GB': /^\d{10}$|^(?!GB|NK|TN|ZZ)(?![DFIQUV])[A-Z](?![DFIQUVO])[A-Z]\d{6}[ABCD ]$/i,
'en-IE': /^\d{7}[A-W][A-IW]{0,1}$/i,
'en-US': /^\d{2}[- ]{0,1}\d{7}$/,
@@ -1126,16 +1156,15 @@ const taxIdFormat = {
'sk-SK': /^\d{6}\/{0,1}\d{3,4}$/,
'sl-SI': /^[1-9]\d{7}$/,
'sv-SE': /^(\d{6}[-+]{0,1}\d{4}|(18|19|20)\d{6}[-+]{0,1}\d{4})$/,
-
};
// taxIdFormat locale aliases
taxIdFormat['lb-LU'] = taxIdFormat['fr-LU'];
taxIdFormat['lt-LT'] = taxIdFormat['et-EE'];
taxIdFormat['nl-BE'] = taxIdFormat['fr-BE'];
+taxIdFormat['fr-CA'] = taxIdFormat['en-CA'];
// Algorithmic tax id check functions for various locales
const taxIdCheck = {
-
'bg-BG': bgBgCheck,
'cs-CZ': csCzCheck,
'de-AT': deAtCheck,
@@ -1143,6 +1172,7 @@ const taxIdCheck = {
'dk-DK': dkDkCheck,
'el-CY': elCyCheck,
'el-GR': elGrCheck,
+ 'en-CA': isCanadianSIN,
'en-IE': enIeCheck,
'en-US': enUsCheck,
'es-ES': esEsCheck,
@@ -1164,12 +1194,12 @@ const taxIdCheck = {
'sk-SK': skSkCheck,
'sl-SI': slSiCheck,
'sv-SE': svSeCheck,
-
};
// taxIdCheck locale aliases
taxIdCheck['lb-LU'] = taxIdCheck['fr-LU'];
taxIdCheck['lt-LT'] = taxIdCheck['et-EE'];
taxIdCheck['nl-BE'] = taxIdCheck['fr-BE'];
+taxIdCheck['fr-CA'] = taxIdCheck['en-CA'];
// Regexes for locales where characters should be omitted before checking format
const allsymbols = /[-\\\/!@#$%\^&\*\(\)\+\=\[\]]+/g;
diff --git a/test/validators.js b/test/validators.js
index 0e68b006f..157abc428 100644
--- a/test/validators.js
+++ b/test/validators.js
@@ -5769,6 +5769,25 @@ describe('Validators', () => {
});
});
+ it('should validate base32 strings with crockford alternative', () => {
+ test({
+ validator: 'isBase32',
+ args: [{ crockford: true }],
+ valid: [
+ '91JPRV3F41BPYWKCCGGG',
+ '60',
+ '64',
+ 'B5QQA833C5Q20S3F41MQ8',
+ ],
+ invalid: [
+ '91JPRV3F41BUPYWKCCGGG',
+ 'B5QQA833C5Q20S3F41MQ8L',
+ '60I',
+ 'B5QQA833OULIC5Q20S3F41MQ8',
+ ],
+ });
+ });
+
it('should validate base58 strings', () => {
test({
validator: 'isBase58',
@@ -6566,6 +6585,25 @@ describe('Validators', () => {
'0-987123456',
],
},
+ {
+ local: 'en-LS',
+ valid: [
+ '+26622123456',
+ '+26628123456',
+ '+26657123456',
+ '+26658123456',
+ '+26659123456',
+ '+26627123456',
+ '+26652123456',
+ ],
+ invalid: [
+ '+26612345678',
+ '',
+ '2664512-21',
+ '+2662212345678',
+ 'someString',
+ ],
+ },
{
locale: 'en-BM',
valid: [
@@ -8477,8 +8515,10 @@ describe('Validators', () => {
'+994502111111',
'0505436743',
'0554328772',
+ '0104328772',
'0993301022',
'+994776007139',
+ '+994106007139',
],
invalid: [
'wrong-number',
@@ -9789,6 +9829,14 @@ describe('Validators', () => {
});
});
+ it('should validate ISO 639-1 language codes', () => {
+ test({
+ validator: 'isISO6391',
+ valid: ['ay', 'az', 'ba', 'be', 'bg'],
+ invalid: ['aj', 'al', 'pe', 'pf', 'abc', '123', ''],
+ });
+ });
+
const validISO8601 = [
'2009-12T12:34',
'2009',
@@ -10167,6 +10215,7 @@ describe('Validators', () => {
' data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E',
'data:,A%20brief%20note',
'data:text/html;charset=US-ASCII,%3Ch1%3EHello!%3C%2Fh1%3E',
+ 'data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,dGVzdC5kb2N4',
],
invalid: [
'dataxbase64',
@@ -10328,6 +10377,23 @@ describe('Validators', () => {
'A1A 1A1',
'X0A-0H0',
'V5K 0A1',
+ 'A1C 3S4',
+ 'A1C3S4',
+ 'a1c 3s4',
+ 'V9A 7N2',
+ 'B3K 5X5',
+ 'K8N 5W6',
+ 'K1A 0B1',
+ 'B1Z 0B9',
+ ],
+ invalid: [
+ ' ',
+ 'invalid value',
+ 'a1a1a',
+ 'A1A 1A1',
+ 'K1A 0D1',
+ 'W1A 0B1',
+ 'Z1A 0B1',
],
},
{
@@ -10533,6 +10599,8 @@ describe('Validators', () => {
'78-399',
'39-490',
'38-483',
+ '05-800',
+ '54-060',
],
},
{
@@ -10591,6 +10659,9 @@ describe('Validators', () => {
'65000',
'65080',
'01000',
+ '51901',
+ '51909',
+ '49125',
],
},
{
@@ -10966,6 +11037,43 @@ describe('Validators', () => {
'658426713',
'558426713'],
});
+ test({
+ validator: 'isTaxID',
+ args: ['en-CA'],
+ valid: [
+ '000000000',
+ '521719666',
+ '469317481',
+ '120217450',
+ '480534858',
+ '325268597',
+ '336475660',
+ '744797853',
+ '130692544',
+ '046454286',
+ ],
+ invalid: [
+ ' ',
+ 'any value',
+ '012345678',
+ '111111111',
+ '999999999',
+ '657449110',
+ '74 47 978 53',
+ '744 797 853',
+ '744-797-853',
+ '981062432',
+ '267500713',
+ '2675o0713',
+ '70597312',
+ '7058973122',
+ '069437151',
+ '046454281',
+ '146452286',
+ '30x92544',
+ '30692544',
+ ],
+ });
test({
validator: 'isTaxID',
args: ['en-GB'],
@@ -11783,6 +11891,44 @@ describe('Validators', () => {
'FS AB 1234 A',
],
});
+ test({
+ validator: 'isLicensePlate',
+ args: ['sv-SE'],
+ valid: [
+ 'ABC 123',
+ 'ABC 12A',
+ 'ABC123',
+ 'ABC12A',
+ 'A WORD',
+ 'WORD',
+ 'ÅSNA',
+ 'EN VARG',
+ 'CERISE',
+ 'AA',
+ 'ABCDEFG',
+ 'ÅÄÖ',
+ 'ÅÄÖ ÅÄÖ',
+ ],
+ invalid: [
+ '',
+ ' ',
+ 'IQV 123',
+ 'IQV123',
+ 'ABI 12Q',
+ 'ÅÄÖ 123',
+ 'ÅÄÖ 12A',
+ 'AB1 A23',
+ 'AB1 12A',
+ 'lower',
+ 'abc 123',
+ 'abc 12A',
+ 'abc 12a',
+ 'AbC 12a',
+ 'WORDLONGERTHANSEVENCHARACTERS',
+ 'A',
+ 'ABC-123',
+ ],
+ });
});
it('should validate VAT numbers', () => {
test({