diff --git a/javascript/i18n/phonenumbers/demo-compiled.js b/javascript/i18n/phonenumbers/demo-compiled.js index ccb01dddc..d23a7e180 100644 --- a/javascript/i18n/phonenumbers/demo-compiled.js +++ b/javascript/i18n/phonenumbers/demo-compiled.js @@ -6,10 +6,10 @@ else if("function"==b&&"undefined"==typeof a.call)return"object";return b}functi function na(a,b,c){if(null==b)c.push("null");else{if("object"==typeof b){if("array"==da(b)){var d=b;b=d.length;c.push("[");for(var e="",f=0;fa.length?!1:N(Za,a)}function hb(a){return N(Xa,a)?O(a,Qa):O(a,L)}function ib(a){var b=hb(a.toString());C(a);a.a(b)}function O(a,b){for(var c=new B,d,e=a.length,f=0;f=e)a=c;else if(d=d.substring(0,e),d=O(d,L),d.length)if(g=g.clone(),Ga(g,4),d=[g],g=w(b,1),c=R(b),g in J){a=T(a,g,U(g));if(e=qb(d,c))d=e.clone(),e=w(e,4),0=f&&f<=e;++f)if(d=parseInt(c.substring(0,f),10),d in J)return b.a(c.substring(f)),d;return 0} -function Ab(a,b,c,d,e){if(!a.length)return 0;a=new B(a);var f;b&&(f=t(b,11));null==f&&(f="NonMatch");var g=a.toString();if(g.length)if(M.test(g))g=g.replace(M,""),C(a),a.a(hb(g)),f=1;else{g=new RegExp(f);ib(a);f=a.toString();if(f.search(g))f=!1;else{var g=f.match(g)[0].length,h=f.substring(g).match(Ta);h&&null!=h[1]&&0=a.b.length)throw"Phone number too short after IDD";if(c=zb(a,c))return u(e, -1,c),c;throw"Invalid country calling code";}if(b&&(f=w(b,10),g=""+f,h=a.toString(),!h.lastIndexOf(g,0))){var m=new B(h.substring(g.length)),h=t(b,1),g=new RegExp(w(h,2));Bb(m,b,null);b=m.toString();h=w(h,3);if(!N(g,a.toString())&&N(g,b)||3==xb(h,a.toString()))return c.a(b),d&&u(e,6,10),u(e,1,f),f}u(e,1,0);return 0} -function Bb(a,b,c){var d=a.toString(),e=d.length,f=t(b,15);if(e&&null!=f&&f.length){var g=new RegExp("^(?:"+f+")");if(e=g.exec(d)){var f=new RegExp(w(t(b,1),2)),h=N(f,d),m=e.length-1;b=t(b,16);if(null!=b&&b.length&&null!=e[m]&&e[m].length){if(d=d.replace(g,b),!h||N(f,d))c&&0b.b.length)throw"The string supplied is too short to be a phone number";g&&(a=new B,c=new B(b.toString()),Bb(c,g,a),e=c.toString(),g=w(t(g,1),3),2!=xb(g,e)&&(b=c,d&&u(f,7,a.toString())));d=b.toString();a=d.length;if(2>a)throw"The string supplied is too short to be a phone number";if(17a.length?!1:N($a,a)}function ib(a){return N(Ya,a)?O(a,Ra):O(a,L)}function jb(a){var b=ib(a.toString());C(a);a.a(b)}function O(a,b){for(var c=new B,d,e=a.length,f=0;f=e)a=c;else if(d=d.substring(0,e),d=O(d,L),d.length)if(g=g.clone(),Ga(g,4),d=[g],g=x(b,1),c=R(b),g in J){a=T(a,g,U(g));if(e=rb(d,c))d=e.clone(),e=x(e,4),0e?2:c[c.length-1]=f&&f<=e;++f)if(d=parseInt(c.substring(0,f),10),d in J)return b.a(c.substring(f)),d;return 0} +function Bb(a,b,c,d,e){if(!a.length)return 0;a=new B(a);var f;b&&(f=t(b,11));null==f&&(f="NonMatch");var g=a.toString();if(g.length)if(M.test(g))g=g.replace(M,""),C(a),a.a(ib(g)),f=1;else{g=new RegExp(f);jb(a);f=a.toString();if(f.search(g))f=!1;else{var g=f.match(g)[0].length,h=f.substring(g).match(Ua);h&&null!=h[1]&&0=a.b.length)throw"Phone number too short after IDD";if(c=Ab(a,c))return u(e, +1,c),c;throw"Invalid country calling code";}if(b&&(f=x(b,10),g=""+f,h=a.toString(),!h.lastIndexOf(g,0))){var m=new B(h.substring(g.length)),g=t(b,1),h=new RegExp(x(g,2));Cb(m,b,null);b=m.toString();if(!N(h,a.toString())&&N(h,b)||3==yb(a.toString(),g))return c.a(b),d&&u(e,6,10),u(e,1,f),f}u(e,1,0);return 0} +function Cb(a,b,c){var d=a.toString(),e=d.length,f=t(b,15);if(e&&null!=f&&f.length){var g=new RegExp("^(?:"+f+")");if(e=g.exec(d)){var f=new RegExp(x(t(b,1),2)),h=N(f,d),m=e.length-1;b=t(b,16);if(null!=b&&b.length&&null!=e[m]&&e[m].length){if(d=d.replace(g,b),!h||N(f,d))c&&0g.b.length)throw"The string supplied is too short to be a phone number";b&&(a=new B,c=new B(g.toString()),Cb(c,b,a),2!=yb(c.toString(),t(b,1))&&(g=c,d&&u(f,7,a.toString())));d=g.toString();a=d.length;if(2>a)throw"The string supplied is too short to be a phone number";if(17} */ i18n.phonenumbers.metadata.countryToMetadata = { -"AD":[,[] -,[] -,[] +"AD":[,[,,"\\d{6}","\\d{6}",,,,,,[6] +] +,[,,"\\d{6}","\\d{6}"] +,[,,"\\d{6}","\\d{6}",,,,,,[6] +] ,[,,"NA","NA",,,,,,[-1] ] ,[,,"NA","NA",,,,,,[-1] @@ -210,9 +212,13 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA",,,,,,[-1] ] ] -,"BB":[,[] -,[] -,[] +,"BB":[,[,,"246\\d{7}","\\d{7,10}",,,,,,[10] +,[7] +] +,[,,"246\\d{7}","\\d{7,10}"] +,[,,"246\\d{7}","\\d{7,10}",,,,,,[10] +,[7] +] ,[,,"NA","NA",,,,,,[-1] ] ,[,,"NA","NA",,,,,,[-1] @@ -232,9 +238,13 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA",,,,,,[-1] ] ] -,"BR":[,[] -,[] -,[] +,"BR":[,[,,"\\d{8,10}","\\d{8,10}",,,,,,[10] +,[8] +] +,[,,"\\d{8,10}","\\d{8,10}"] +,[,,"\\d{8,10}","\\d{8,10}",,,,,,[10] +,[8] +] ,[,,"NA","NA",,,,,,[-1] ] ,[,,"NA","NA",,,,,,[-1] @@ -307,9 +317,13 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA",,,,,,[-1] ] ] -,"CA":[,[] -,[] -,[] +,"CA":[,[,,"226\\d{7}","\\d{7,10}",,,,,,[10] +,[7] +] +,[,,"226\\d{7}","\\d{7,10}"] +,[,,"226\\d{7}","\\d{7,10}",,,,,,[10] +,[7] +] ,[,,"NA","NA",,,,,,[-1] ] ,[,,"NA","NA",,,,,,[-1] @@ -329,9 +343,13 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA",,,,,,[-1] ] ] -,"CC":[,[] -,[] -,[] +,"CC":[,[,,"\\d{6,10}","\\d{6,10}",,,,,,[10] +,[6] +] +,[,,"\\d{6,10}","\\d{6,10}"] +,[,,"\\d{6,10}","\\d{6,10}",,,,,,[10] +,[6] +] ,[,,"NA","NA",,,,,,[-1] ] ,[,,"NA","NA",,,,,,[-1] @@ -379,9 +397,13 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA",,,,,,[-1] ] ] -,"CX":[,[] -,[] -,[] +,"CX":[,[,,"\\d{8,10}","\\d{8,10}",,,,,,[10] +,[8] +] +,[,,"\\d{8,10}","\\d{8,10}"] +,[,,"\\d{8,10}","\\d{8,10}",,,,,,[10] +,[8] +] ,[,,"NA","NA",,,,,,[-1] ] ,[,,"NA","NA",,,,,,[-1] @@ -439,9 +461,11 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA",,,,,,[-1] ] ] -,"FR":[,[,,"3\\d{6}","\\d{7}"] -,[,,"3\\d{6}","\\d{7}"] +,"FR":[,[,,"3\\d{6}","\\d{7}",,,,,,[7] +] ,[,,"3\\d{6}","\\d{7}"] +,[,,"3\\d{6}","\\d{7}",,,,,,[7] +] ,[,,"NA","NA",,,,,,[-1] ] ,[,,"NA","NA",,,,,,[-1] @@ -464,16 +488,22 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA",,,,,,[-1] ] ] -,"GB":[,[,,"\\d{10}","\\d{6,10}",,,,,,[10] -,[6] +,"GB":[,[,,"\\d{10}","\\d{6,10}",,,,,,[9,10] +,[6,7,8] ] ,[,,"[1-6]\\d{9}","\\d{6,10}"] -,[,,"7[1-57-9]\\d{8}","\\d{10}"] -,[,,"80\\d{8}","\\d{10}"] -,[,,"9[018]\\d{8}","\\d{10}"] -,[,,"8(?:4[3-5]|7[0-2])\\d{7}","\\d{10}"] -,[,,"70\\d{8}","\\d{10}"] -,[,,"56\\d{8}","\\d{10}"] +,[,,"7[1-57-9]\\d{8}","\\d{10}",,,,,,[10] +] +,[,,"80\\d{8}","\\d{10}",,,,,,[10] +] +,[,,"9[018]\\d{8}","\\d{10}",,,,,,[10] +] +,[,,"8(?:4[3-5]|7[0-2])\\d{7}","\\d{10}",,,,,,[10] +] +,[,,"70\\d{8}","\\d{10}",,,,,,[10] +] +,[,,"56\\d{8}","\\d{10}",,,,,,[10] +] ,"GB",44,"00","0",,,"0",,,,[[,"(\\d{2})(\\d{4})(\\d{4})","$1 $2 $3",["[1-59]|[78]0"] ,"(0$1)"] ,[,"(\\d)(\\d{3})(\\d{3})(\\d{3})","$1 $2 $3 $4",["6"] @@ -483,7 +513,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,[,"(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3",["8[47]"] ,"(0$1)"] ] -,,[,,"76\\d{8}","\\d{10}"] +,,[,,"76\\d{8}","\\d{10}",,,,,,[10] +] ,,,[,,"NA","NA",,,,,,[-1] ] ,[,,"NA","NA",,,,,,[-1] @@ -491,9 +522,13 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA",,,,,,[-1] ] ] -,"GG":[,[] -,[] -,[] +,"GG":[,[,,"\\d{6,10}","\\d{6,10}",,,,,,[10] +,[6] +] +,[,,"\\d{6,10}","\\d{6,10}"] +,[,,"\\d{6,10}","\\d{6,10}",,,,,,[10] +,[6] +] ,[,,"NA","NA",,,,,,[-1] ] ,[,,"NA","NA",,,,,,[-1] @@ -786,9 +821,11 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA",,,,,,[-1] ] ] -,"SE":[,[] -,[] -,[] +,"SE":[,[,,"\\d{9}","\\d{9}",,,,,,[9] +] +,[,,"\\d{9}","\\d{9}"] +,[,,"\\d{9}","\\d{9}",,,,,,[9] +] ,[,,"NA","NA",,,,,,[-1] ] ,[,,"NA","NA",,,,,,[-1] @@ -841,10 +878,11 @@ i18n.phonenumbers.metadata.countryToMetadata = { ] ] ,"US":[,[,,"[13-689]\\d{9}|2[0-35-9]\\d{8}","\\d{7}(?:\\d{3})?",,,"1234567890",,,[10] +,[7] ] +,[,,"[13-689]\\d{9}|2[0-35-9]\\d{8}","\\d{7}(?:\\d{3})?",,,"1234567890"] ,[,,"[13-689]\\d{9}|2[0-35-9]\\d{8}","\\d{7}(?:\\d{3})?",,,"1234567890",,,[10] -] -,[,,"[13-689]\\d{9}|2[0-35-9]\\d{8}","\\d{7}(?:\\d{3})?",,,"1234567890",,,[10] +,[7] ] ,[,,"8(?:00|66|77|88)\\d{7}","\\d{10}",,,"1234567890"] ,[,,"900\\d{7}","\\d{10}",,,"1234567890"] diff --git a/javascript/i18n/phonenumbers/phonenumberutil.js b/javascript/i18n/phonenumbers/phonenumberutil.js index 2b20e4aec..0d471dc0a 100644 --- a/javascript/i18n/phonenumbers/phonenumberutil.js +++ b/javascript/i18n/phonenumbers/phonenumberutil.js @@ -26,7 +26,7 @@ * the codes can be found here: * http://www.iso.org/iso/english_country_names_and_code_elements * - * @author Nikolaos Trogkanis + * Credits to Nikolaos Trogkanis for original implementation. */ goog.provide('i18n.phonenumbers.Error'); @@ -1763,8 +1763,9 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatNumberForMobileDialing = /** @type {i18n.phonenumbers.PhoneMetadata} */ var regionMetadata = this.getMetadataForRegion(regionCallingFrom); if (this.canBeInternationallyDialled(numberNoExt) && - !this.isShorterThanPossibleNormalNumber_( - regionMetadata, this.getNationalSignificantNumber(numberNoExt))) { + this.testNumberLength_(this.getNationalSignificantNumber(numberNoExt), + regionMetadata.getGeneralDesc()) != + i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT) { formattedNumber = this.format( numberNoExt, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL); } else { @@ -2770,11 +2771,17 @@ i18n.phonenumbers.PhoneNumberUtil.prototype. */ i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatchingDesc_ = function(nationalNumber, numberDesc) { - + // Check if any possible number lengths are present; if so, we use them to + // avoid checking the validation pattern if they don't match. If they are + // absent, this means they match the general description, which we have + // already checked before a specific number type. + var actualLength = nationalNumber.length; + if (numberDesc.possibleLengthCount() > 0 && + numberDesc.possibleLengthArray().indexOf(actualLength) == -1) { + return false; + } return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_( - numberDesc.getPossibleNumberPatternOrDefault(), nationalNumber) && - i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_( - numberDesc.getNationalNumberPatternOrDefault(), nationalNumber); + numberDesc.getNationalNumberPatternOrDefault(), nationalNumber); }; @@ -3113,41 +3120,40 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumber = * in between these possible lengths is entered, such as of length 8, this will * return TOO_LONG. * - * @param {string} numberPattern * @param {string} number + * @param {i18n.phonenumbers.PhoneNumberDesc} phoneNumberDesc * @return {i18n.phonenumbers.PhoneNumberUtil.ValidationResult} * @private */ -i18n.phonenumbers.PhoneNumberUtil.prototype.testNumberLengthAgainstPattern_ = - function(numberPattern, number) { - if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(numberPattern, - number)) { +i18n.phonenumbers.PhoneNumberUtil.prototype.testNumberLength_ = + function(number, phoneNumberDesc) { + var possibleLengths = phoneNumberDesc.possibleLengthArray(); + var localLengths = phoneNumberDesc.possibleLengthLocalOnlyArray(); + var actualLength = number.length; + if (localLengths.indexOf(actualLength) > -1) { return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE; } - if (number.search(numberPattern) == 0) { - return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG; - } else { + // There should always be "possibleLengths" set for every element. This will + // be a build-time check once ShortNumberMetadata.xml is migrated to contain + // this information as well. + var minimumLength = possibleLengths[0]; + if (minimumLength == actualLength) { + return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE; + } else if (minimumLength > actualLength) { return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT; + } else if (possibleLengths[possibleLengths.length - 1] < actualLength) { + return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG; } -}; - - -/** - * Helper method to check whether a number is too short to be a regular length - * phone number in a region. - * - * @param {i18n.phonenumbers.PhoneMetadata} regionMetadata - * @param {string} number - * @return {boolean} - * @private - */ -i18n.phonenumbers.PhoneNumberUtil.prototype.isShorterThanPossibleNormalNumber_ = - function(regionMetadata, number) { - /** @type {string} */ - var possibleNumberPattern = - regionMetadata.getGeneralDesc().getPossibleNumberPatternOrDefault(); - return this.testNumberLengthAgainstPattern_(possibleNumberPattern, number) == - i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT; + // Note that actually the number is not too long if possible_lengths does not + // contain the length: we know it is less than the highest possible number + // length, and higher than the lowest possible number length. However, we + // don't currently have an enum to express this, so we return TOO_LONG in the + // short-term. + // We could skip the first element; we've already checked it; but we prefer to + // check one value rather than create an extra object in this case. + return (possibleLengths.indexOf(actualLength) > -1) ? + i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE : + i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG; }; @@ -3198,11 +3204,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberWithReason = /** @type {i18n.phonenumbers.PhoneMetadata} */ var metadata = this.getMetadataForRegionOrCallingCode_(countryCode, regionCode); - /** @type {string} */ - var possibleNumberPattern = - metadata.getGeneralDesc().getPossibleNumberPatternOrDefault(); - return this.testNumberLengthAgainstPattern_(possibleNumberPattern, - nationalNumber); + return this.testNumberLength_(nationalNumber, metadata.getGeneralDesc()); }; @@ -3416,9 +3418,6 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.maybeExtractCountryCode = potentialNationalNumber, defaultRegionMetadata, null); /** @type {string} */ var potentialNationalNumberStr = potentialNationalNumber.toString(); - /** @type {string} */ - var possibleNumberPattern = - generalDesc.getPossibleNumberPatternOrDefault(); // If the number was not valid before but is valid now, or if it was too // long before, we consider the number with the country calling code // stripped to be a better result and keep that instead. @@ -3426,8 +3425,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.maybeExtractCountryCode = validNumberPattern, fullNumber.toString()) && i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_( validNumberPattern, potentialNationalNumberStr)) || - this.testNumberLengthAgainstPattern_(possibleNumberPattern, - fullNumber.toString()) == + this.testNumberLength_(fullNumber.toString(), generalDesc) == i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG) { nationalNumber.append(potentialNationalNumberStr); if (keepRawInput) { @@ -3899,8 +3897,13 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ = new goog.string.StringBuffer(normalizedNationalNumber.toString()); this.maybeStripNationalPrefixAndCarrierCode( potentialNationalNumber, regionMetadata, carrierCode); - if (!this.isShorterThanPossibleNormalNumber_( - regionMetadata, potentialNationalNumber.toString())) { + // We require that the NSN remaining after stripping the national prefix and + // carrier code be long enough to be a possible length for the region. + // Otherwise, we don't do the stripping, since the original number could be + // a valid short number. + if (this.testNumberLength_(potentialNationalNumber.toString(), + regionMetadata.getGeneralDesc()) != + i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT) { normalizedNationalNumber = potentialNationalNumber; if (keepRawInput) { phoneNumber.setPreferredDomesticCarrierCode(carrierCode.toString()); diff --git a/tools/java/java-build/target/java-build-1.0-SNAPSHOT-jar-with-dependencies.jar b/tools/java/java-build/target/java-build-1.0-SNAPSHOT-jar-with-dependencies.jar index 2450141e2..ff256615b 100644 Binary files a/tools/java/java-build/target/java-build-1.0-SNAPSHOT-jar-with-dependencies.jar and b/tools/java/java-build/target/java-build-1.0-SNAPSHOT-jar-with-dependencies.jar differ