DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (777e60ca8853)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

this.EXPORTED_SYMBOLS = ["TelURIParser"];

/**
 * Singleton providing functionality for parsing tel: and sms: URIs
 */
this.TelURIParser = {
  parseURI: function(scheme, uri) {
    // https://www.ietf.org/rfc/rfc2806.txt
    let subscriber = decodeURIComponent(uri.slice((scheme + ':').length));

    if (!subscriber.length) {
      return null;
    }

    let number = '';
    let pos = 0;
    let len = subscriber.length;

    // visual-separator
    let visualSeparator = [ ' ', '-', '.', '(', ')' ];
    let digits = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ];
    let dtmfDigits = [ '*', '#', 'A', 'B', 'C', 'D' ];
    let pauseCharacter = [ 'p', 'w' ];

    // global-phone-number
    if (subscriber[pos] == '+') {
      number += '+';
      for (++pos; pos < len; ++pos) {
        if (visualSeparator.indexOf(subscriber[pos]) != -1) {
          number += subscriber[pos];
        } else if (digits.indexOf(subscriber[pos]) != -1) {
          number += subscriber[pos];
        } else {
          break;
        }
      }
    }
    // local-phone-number
    else {
      for (; pos < len; ++pos) {
        if (visualSeparator.indexOf(subscriber[pos]) != -1) {
          number += subscriber[pos];
        } else if (digits.indexOf(subscriber[pos]) != -1) {
          number += subscriber[pos];
        } else if (dtmfDigits.indexOf(subscriber[pos]) != -1) {
          number += subscriber[pos];
        } else if (pauseCharacter.indexOf(subscriber[pos]) != -1) {
          number += subscriber[pos];
        } else {
          break;
        }
      }

      // this means error
      if (!number.length) {
        return null;
      }

      // isdn-subaddress
      if (subscriber.substring(pos, pos + 6) == ';isub=') {
        let subaddress = '';

        for (pos += 6; pos < len; ++pos) {
          if (visualSeparator.indexOf(subscriber[pos]) != -1) {
            subaddress += subscriber[pos];
          } else if (digits.indexOf(subscriber[pos]) != -1) {
            subaddress += subscriber[pos];
          } else {
            break;
          }
        }

        // FIXME: ignore subaddress - Bug 795242
      }

      // post-dial
      if (subscriber.substring(pos, pos + 7) == ';postd=') {
        let subaddress = '';

        for (pos += 7; pos < len; ++pos) {
          if (visualSeparator.indexOf(subscriber[pos]) != -1) {
            subaddress += subscriber[pos];
          } else if (digits.indexOf(subscriber[pos]) != -1) {
            subaddress += subscriber[pos];
          } else if (dtmfDigits.indexOf(subscriber[pos]) != -1) {
            subaddress += subscriber[pos];
          } else if (pauseCharacter.indexOf(subscriber[pos]) != -1) {
            subaddress += subscriber[pos];
          } else {
            break;
          }
        }

        // FIXME: ignore subaddress - Bug 795242
      }

      // area-specific
      if (subscriber.substring(pos, pos + 15) == ';phone-context=') {
        pos += 15;

        // global-network-prefix | local-network-prefix | private-prefi
        number = subscriber.substring(pos, subscriber.length) + number;
      }
    }

    // Ignore MWI and USSD codes. See 794034.
    if (number.match(/[#\*]/) && !number.match(/^[#\*]\d+$/)) {
      return null;
    }

    return number || null;
  }
};