summaryrefslogtreecommitdiffstats
path: root/b2g/components/TelURIParser.jsm
blob: 46b0bb8fd32ae7c3b5a4591486663c64ac11f214 (plain)
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;
  }
};