Browse Source

[RN] Don't override config values

master
Lyubo Marinov 7 years ago
parent
commit
96e0c56bde

+ 1
- 1
conference.js View File

@@ -19,7 +19,6 @@ import analytics from './modules/analytics/analytics';
19 19
 
20 20
 import EventEmitter from "events";
21 21
 
22
-import { getLocationContextRoot } from './react/features/app';
23 22
 import {
24 23
     AVATAR_ID_COMMAND,
25 24
     AVATAR_URL_COMMAND,
@@ -50,6 +49,7 @@ import {
50 49
     trackAdded,
51 50
     trackRemoved
52 51
 } from './react/features/base/tracks';
52
+import { getLocationContextRoot } from './react/features/base/util';
53 53
 import { statsEmitter } from './react/features/connection-indicator';
54 54
 import { showDesktopPicker } from  './react/features/desktop-picker';
55 55
 import {

+ 4
- 8
react/features/app/actions.js View File

@@ -2,9 +2,9 @@ import { setRoom } from '../base/conference';
2 2
 import { setLocationURL } from '../base/connection';
3 3
 import { setConfig } from '../base/config';
4 4
 import { loadConfig } from '../base/lib-jitsi-meet';
5
+import { parseURIString } from '../base/util';
5 6
 
6 7
 import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from './actionTypes';
7
-import { _parseURIString } from './functions';
8 8
 
9 9
 declare var APP: Object;
10 10
 
@@ -19,9 +19,7 @@ declare var APP: Object;
19 19
  */
20 20
 export function appNavigate(uri: ?string) {
21 21
     return (dispatch: Dispatch<*>, getState: Function) =>
22
-        _appNavigateToOptionalLocation(
23
-            dispatch, getState,
24
-            _parseURIString(uri));
22
+        _appNavigateToOptionalLocation(dispatch, getState, parseURIString(uri));
25 23
 }
26 24
 
27 25
 /**
@@ -133,7 +131,7 @@ function _appNavigateToOptionalLocation(
133 131
     // default.
134 132
     if (!location || !location.host) {
135 133
         const defaultLocation
136
-            = _parseURIString(getState()['features/app'].app._getDefaultURL());
134
+            = parseURIString(getState()['features/app'].app._getDefaultURL());
137 135
 
138 136
         if (location) {
139 137
             location.host = defaultLocation.host;
@@ -211,9 +209,7 @@ function _loadConfig(location: Object) {
211 209
 
212 210
     // The React Native app supports an app-specific scheme which is sure to not
213 211
     // be supported by fetch (or whatever loadConfig utilizes).
214
-    if (protocol !== 'http:' && protocol !== 'https:') {
215
-        protocol = 'https:';
216
-    }
212
+    protocol !== 'http:' && protocol !== 'https:' && (protocol = 'https:');
217 213
 
218 214
     // TDOO userinfo
219 215
 

+ 3
- 3
react/features/app/components/App.web.js View File

@@ -1,8 +1,8 @@
1
-import { AbstractApp } from './AbstractApp';
2
-import { getLocationContextRoot } from '../functions';
3
-
1
+import { getLocationContextRoot } from '../../base/util';
4 2
 import '../../room-lock';
5 3
 
4
+import { AbstractApp } from './AbstractApp';
5
+
6 6
 /**
7 7
  * Root application component.
8 8
  *

+ 0
- 260
react/features/app/functions.native.js View File

@@ -3,132 +3,6 @@ import { RouteRegistry } from '../base/react';
3 3
 import { Conference } from '../conference';
4 4
 import { WelcomePage } from '../welcome';
5 5
 
6
-/**
7
- * The RegExp pattern of the authority of a URI.
8
- *
9
- * @private
10
- * @type {string}
11
- */
12
-const _URI_AUTHORITY_PATTERN = '(//[^/?#]+)';
13
-
14
-/**
15
- * The RegExp pattern of the path of a URI.
16
- *
17
- * @private
18
- * @type {string}
19
- */
20
-const _URI_PATH_PATTERN = '([^?#]*)';
21
-
22
-/**
23
- * The RegExp patther of the protocol of a URI.
24
- *
25
- * @private
26
- * @type {string}
27
- */
28
-const _URI_PROTOCOL_PATTERN = '([a-z][a-z0-9\\.\\+-]*:)';
29
-
30
-/**
31
- * Fixes the hier-part of a specific URI (string) so that the URI is well-known.
32
- * For example, certain Jitsi Meet deployments are not conventional but it is
33
- * possible to translate their URLs into conventional.
34
- *
35
- * @param {string} uri - The URI (string) to fix the hier-part of.
36
- * @private
37
- * @returns {string}
38
- */
39
-function _fixURIStringHierPart(uri) {
40
-    // Rewrite the specified URL in order to handle special cases such as
41
-    // hipchat.com and enso.me which do not follow the common pattern of most
42
-    // Jitsi Meet deployments.
43
-
44
-    // hipchat.com
45
-    let regex
46
-        = new RegExp(
47
-            `^${_URI_PROTOCOL_PATTERN}//hipchat\\.com/video/call/`,
48
-            'gi');
49
-    let match = regex.exec(uri);
50
-
51
-    if (!match) {
52
-        // enso.me
53
-        regex
54
-            = new RegExp(
55
-                `^${_URI_PROTOCOL_PATTERN}//enso\\.me/(?:call|meeting)/`,
56
-                'gi');
57
-        match = regex.exec(uri);
58
-    }
59
-    if (match) {
60
-        /* eslint-disable no-param-reassign, prefer-template */
61
-
62
-        uri
63
-            = match[1] /* protocol */
64
-                + '//enso.hipchat.me/'
65
-                + uri.substring(regex.lastIndex); /* room (name) */
66
-
67
-        /* eslint-enable no-param-reassign, prefer-template */
68
-    }
69
-
70
-    return uri;
71
-}
72
-
73
-/**
74
- * Fixes the scheme part of a specific URI (string) so that it contains a
75
- * well-known scheme such as HTTP(S). For example, the mobile app implements an
76
- * app-specific URI scheme in addition to Universal Links. The app-specific
77
- * scheme may precede or replace the well-known scheme. In such a case, dealing
78
- * with the app-specific scheme only complicates the logic and it is simpler to
79
- * get rid of it (by translating the app-specific scheme into a well-known
80
- * scheme).
81
- *
82
- * @param {string} uri - The URI (string) to fix the scheme of.
83
- * @private
84
- * @returns {string}
85
- */
86
-function _fixURIStringScheme(uri) {
87
-    const regex = new RegExp(`^${_URI_PROTOCOL_PATTERN}+`, 'gi');
88
-    const match = regex.exec(uri);
89
-
90
-    if (match) {
91
-        // As an implementation convenience, pick up the last scheme and make
92
-        // sure that it is a well-known one.
93
-        let protocol = match[match.length - 1].toLowerCase();
94
-
95
-        if (protocol !== 'http:' && protocol !== 'https:') {
96
-            protocol = 'https:';
97
-        }
98
-
99
-        /* eslint-disable no-param-reassign */
100
-
101
-        uri = uri.substring(regex.lastIndex);
102
-        if (uri.startsWith('//')) {
103
-            // The specified URL was not a room name only, it contained an
104
-            // authority.
105
-            uri = protocol + uri;
106
-        }
107
-
108
-        /* eslint-enable no-param-reassign */
109
-    }
110
-
111
-    return uri;
112
-}
113
-
114
-/**
115
- * Gets the (Web application) context root defined by a specific location (URI).
116
- *
117
- * @param {Object} location - The location (URI) which defines the (Web
118
- * application) context root.
119
- * @returns {string} - The (Web application) context root defined by the
120
- * specified {@code location} (URI).
121
- */
122
-export function getLocationContextRoot(location: Object) {
123
-    const pathname = location.pathname;
124
-    const contextRootEndIndex = pathname.lastIndexOf('/');
125
-
126
-    return (
127
-        contextRootEndIndex === -1
128
-            ? '/'
129
-            : pathname.substring(0, contextRootEndIndex + 1));
130
-}
131
-
132 6
 /**
133 7
  * Determines which route is to be rendered in order to depict a specific Redux
134 8
  * store.
@@ -159,137 +33,3 @@ export function _getRouteToRender(stateOrGetState) {
159 33
 
160 34
     return RouteRegistry.getRouteByComponent(component);
161 35
 }
162
-
163
-/**
164
- * Parses a specific URI string into an object with the well-known properties of
165
- * the {@link Location} and/or {@link URL} interfaces implemented by Web
166
- * browsers. The parsing attempts to be in accord with IETF's RFC 3986.
167
- *
168
- * @param {string} str - The URI string to parse.
169
- * @returns {{
170
- *     hash: string,
171
- *     host: (string|undefined),
172
- *     hostname: (string|undefined),
173
- *     pathname: string,
174
- *     port: (string|undefined),
175
- *     protocol: (string|undefined),
176
- *     search: string
177
- * }}
178
- */
179
-function _parseStandardURIString(str: string) {
180
-    /* eslint-disable no-param-reassign */
181
-
182
-    const obj = {};
183
-
184
-    let regex;
185
-    let match;
186
-
187
-    // protocol
188
-    regex = new RegExp(`^${_URI_PROTOCOL_PATTERN}`, 'gi');
189
-    match = regex.exec(str);
190
-    if (match) {
191
-        obj.protocol = match[1].toLowerCase();
192
-        str = str.substring(regex.lastIndex);
193
-    }
194
-
195
-    // authority
196
-    regex = new RegExp(`^${_URI_AUTHORITY_PATTERN}`, 'gi');
197
-    match = regex.exec(str);
198
-    if (match) {
199
-        let authority = match[1].substring(/* // */ 2);
200
-
201
-        str = str.substring(regex.lastIndex);
202
-
203
-        // userinfo
204
-        const userinfoEndIndex = authority.indexOf('@');
205
-
206
-        if (userinfoEndIndex !== -1) {
207
-            authority = authority.substring(userinfoEndIndex + 1);
208
-        }
209
-
210
-        obj.host = authority;
211
-
212
-        // port
213
-        const portBeginIndex = authority.lastIndexOf(':');
214
-
215
-        if (portBeginIndex !== -1) {
216
-            obj.port = authority.substring(portBeginIndex + 1);
217
-            authority = authority.substring(0, portBeginIndex);
218
-        }
219
-
220
-        // hostname
221
-        obj.hostname = authority;
222
-    }
223
-
224
-    // pathname
225
-    regex = new RegExp(`^${_URI_PATH_PATTERN}`, 'gi');
226
-    match = regex.exec(str);
227
-
228
-    let pathname;
229
-
230
-    if (match) {
231
-        pathname = match[1];
232
-        str = str.substring(regex.lastIndex);
233
-    }
234
-    if (pathname) {
235
-        if (!pathname.startsWith('/')) {
236
-            pathname = `/${pathname}`;
237
-        }
238
-    } else {
239
-        pathname = '/';
240
-    }
241
-    obj.pathname = pathname;
242
-
243
-    // query
244
-    if (str.startsWith('?')) {
245
-        let hashBeginIndex = str.indexOf('#', 1);
246
-
247
-        if (hashBeginIndex === -1) {
248
-            hashBeginIndex = str.length;
249
-        }
250
-        obj.search = str.substring(0, hashBeginIndex);
251
-        str = str.substring(hashBeginIndex);
252
-    } else {
253
-        obj.search = ''; // Google Chrome
254
-    }
255
-
256
-    // fragment
257
-    obj.hash = str.startsWith('#') ? str : '';
258
-
259
-    /* eslint-enable no-param-reassign */
260
-
261
-    return obj;
262
-}
263
-
264
-/**
265
- * Parses a specific URI which (supposedly) references a Jitsi Meet resource
266
- * (location).
267
- *
268
- * @param {(string|undefined)} uri - The URI to parse which (supposedly)
269
- * references a Jitsi Meet resource (location).
270
- * @returns {{
271
- *     room: (string|undefined)
272
- * }}
273
- */
274
-export function _parseURIString(uri: ?string) {
275
-    if (typeof uri !== 'string') {
276
-        return undefined;
277
-    }
278
-
279
-    const obj
280
-        = _parseStandardURIString(
281
-            _fixURIStringHierPart(_fixURIStringScheme(uri)));
282
-
283
-    // Add the properties that are specific to a Jitsi Meet resource (location)
284
-    // such as contextRoot, room:
285
-
286
-    // contextRoot
287
-    obj.contextRoot = getLocationContextRoot(obj);
288
-
289
-    // The room (name) is the last component of pathname.
290
-    const { pathname } = obj;
291
-
292
-    obj.room = pathname.substring(pathname.lastIndexOf('/') + 1) || undefined;
293
-
294
-    return obj;
295
-}

+ 0
- 2
react/features/app/functions.web.js View File

@@ -71,8 +71,6 @@ const _INTERCEPT_COMPONENT_RULES = [
71 71
     }
72 72
 ];
73 73
 
74
-export { getLocationContextRoot, _parseURIString } from './functions.native';
75
-
76 74
 /**
77 75
  * Determines which route is to be rendered in order to depict a specific Redux
78 76
  * store.

+ 48
- 22
react/features/base/connection/actions.native.js View File

@@ -1,9 +1,11 @@
1 1
 /* @flow */
2 2
 
3
+import _ from 'lodash';
3 4
 import type { Dispatch } from 'redux';
4 5
 
5 6
 import { conferenceWillLeave } from '../conference';
6 7
 import JitsiMeetJS, { JitsiConnectionEvents } from '../lib-jitsi-meet';
8
+import { parseStandardURIString } from '../util';
7 9
 
8 10
 import {
9 11
     CONNECTION_DISCONNECTED,
@@ -21,29 +23,8 @@ import {
21 23
 export function connect() {
22 24
     return (dispatch: Dispatch<*>, getState: Function) => {
23 25
         const state = getState();
24
-        let { options } = state['features/base/connection'];
25
-
26
-        options = {
27
-            // Lib-jitsi-meet wants the config passed in multiple places and
28
-            // here is the latest one I have discovered.
29
-            ...state['features/base/config'],
30
-
31
-            // TODO It is probable that config should override the options that
32
-            // have been automatically constructed by the app. Unfortunately,
33
-            // config may specify URLs such as bosh at the time of this writing
34
-            // which react-native cannot parse (because they do not have a
35
-            // protocol/scheme).
36
-            ...options
37
-        };
38
-
26
+        const options = _constructOptions(state);
39 27
         const { issuer, jwt } = state['features/jwt'];
40
-        const { room } = state['features/base/conference'];
41
-
42
-        // XXX The Jitsi Meet deployments require the room argument to be in
43
-        // lower case at the time of this writing but, unfortunately, they do
44
-        // not ignore case themselves.
45
-        options.bosh += room ? `?room=${room.toLowerCase()}` : '';
46
-
47 28
         const connection
48 29
             = new JitsiMeetJS.JitsiConnection(
49 30
                 options.appId,
@@ -202,6 +183,51 @@ export function connectionFailed(
202 183
     };
203 184
 }
204 185
 
186
+/**
187
+ * Constructs options to be passed to the constructor of {@code JitsiConnection}
188
+ * based on the redux state.
189
+ *
190
+ * @param {Object} state - The redux state.
191
+ * @returns {Object} The options to be passed to the constructor of
192
+ * {@code JitsiConnection}.
193
+ */
194
+function _constructOptions(state) {
195
+    const defaultOptions = state['features/base/connection'].options;
196
+    const options = _.merge(
197
+        {},
198
+        defaultOptions,
199
+
200
+        // Lib-jitsi-meet wants the config passed in multiple places and here is
201
+        // the latest one I have discovered.
202
+        state['features/base/config'],
203
+    );
204
+    let { bosh } = options;
205
+
206
+    if (bosh) {
207
+        // Append room to the URL's search.
208
+        const { room } = state['features/base/conference'];
209
+
210
+        // XXX The Jitsi Meet deployments require the room argument to be in
211
+        // lower case at the time of this writing but, unfortunately, they do
212
+        // not ignore case themselves.
213
+        room && (bosh += `?room=${room.toLowerCase()}`);
214
+
215
+        // XXX By default, config.js does not add a protocol to the BOSH URL.
216
+        // Which trips React Native. Make sure there is a protocol in order to
217
+        // satisfy React Native.
218
+        if (bosh !== defaultOptions.bosh
219
+                && !parseStandardURIString(bosh).protocol) {
220
+            const { protocol } = parseStandardURIString(defaultOptions.bosh);
221
+
222
+            protocol && (bosh = protocol + bosh);
223
+        }
224
+
225
+        options.bosh = bosh;
226
+    }
227
+
228
+    return options;
229
+}
230
+
205 231
 /**
206 232
  * Closes connection.
207 233
  *

+ 20
- 19
react/features/base/connection/reducer.js View File

@@ -1,6 +1,7 @@
1 1
 /* @flow */
2 2
 
3 3
 import { assign, ReducerRegistry, set } from '../redux';
4
+import { parseURIString } from '../util';
4 5
 
5 6
 import {
6 7
     CONNECTION_DISCONNECTED,
@@ -119,38 +120,38 @@ function _connectionWillConnect(
119 120
 
120 121
 /**
121 122
  * Constructs options to be passed to the constructor of {@code JitsiConnection}
122
- * based on a specific domain.
123
+ * based on a specific location URL.
123 124
  *
124
- * @param {string} domain - The domain with which the returned options are to be
125
- * populated.
125
+ * @param {string} locationURL - The location URL with which the returned
126
+ * options are to be constructed.
126 127
  * @private
127
- * @returns {Object}
128
+ * @returns {Object} The options to be passed to the constructor of
129
+ * {@code JitsiConnection} based on the location URL.
128 130
  */
129
-function _constructOptions(domain: string) {
131
+function _constructOptions(locationURL: URL) {
132
+    const locationURI = parseURIString(locationURL.href);
133
+
130 134
     // FIXME The HTTPS scheme for the BOSH URL works with meet.jit.si on both
131 135
     // mobile & Web. It also works with beta.meet.jit.si on Web. Unfortunately,
132 136
     // it doesn't work with beta.meet.jit.si on mobile. Temporarily, use the
133 137
     // HTTP scheme for the BOSH URL with beta.meet.jit.si on mobile.
134
-    let boshProtocol;
138
+    let { protocol } = locationURI;
139
+    const domain = locationURI.hostname;
135 140
 
136
-    if (domain === 'beta.meet.jit.si') {
137
-        if (typeof window === 'object') {
138
-            const windowLocation = window.location;
141
+    if (!protocol && domain === 'beta.meet.jit.si') {
142
+        const windowLocation = window.location;
139 143
 
140
-            if (windowLocation) {
141
-                // React Native doesn't have a window.location at the time of
142
-                // this writing, let alone a window.location.protocol.
143
-                boshProtocol = windowLocation.protocol;
144
-            }
145
-        }
146
-        boshProtocol || (boshProtocol = 'http:');
144
+        windowLocation && (protocol = windowLocation.protocol);
145
+        protocol || (protocol = 'http:');
147 146
     }
148 147
 
149 148
     // Default to the HTTPS scheme for the BOSH URL.
150
-    boshProtocol || (boshProtocol = 'https:');
149
+    protocol || (protocol = 'https:');
151 150
 
152 151
     return {
153
-        bosh: `${String(boshProtocol)}//${domain}/http-bind`,
152
+        bosh:
153
+            `${String(protocol)}//${domain}${locationURI.contextRoot || '/'
154
+                }http-bind`,
154 155
         hosts: {
155 156
             domain,
156 157
 
@@ -176,6 +177,6 @@ function _setLocationURL(
176 177
         { locationURL }: { locationURL: ?URL }) {
177 178
     return assign(state, {
178 179
         locationURL,
179
-        options: locationURL ? _constructOptions(locationURL.host) : undefined
180
+        options: locationURL ? _constructOptions(locationURL) : undefined
180 181
     });
181 182
 }

+ 1
- 0
react/features/base/util/index.js View File

@@ -1,2 +1,3 @@
1 1
 export * from './loadScript';
2 2
 export * from './randomUtil';
3
+export * from './uri';

+ 264
- 0
react/features/base/util/uri.js View File

@@ -0,0 +1,264 @@
1
+/* @flow */
2
+
3
+/**
4
+ * The {@link RegExp} pattern of the authority of a URI.
5
+ *
6
+ * @private
7
+ * @type {string}
8
+ */
9
+const _URI_AUTHORITY_PATTERN = '(//[^/?#]+)';
10
+
11
+/**
12
+ * The {@link RegExp} pattern of the path of a URI.
13
+ *
14
+ * @private
15
+ * @type {string}
16
+ */
17
+const _URI_PATH_PATTERN = '([^?#]*)';
18
+
19
+/**
20
+ * The {@link RegExp} pattern of the protocol of a URI.
21
+ *
22
+ * @private
23
+ * @type {string}
24
+ */
25
+const _URI_PROTOCOL_PATTERN = '([a-z][a-z0-9\\.\\+-]*:)';
26
+
27
+/**
28
+ * Fixes the hier-part of a specific URI (string) so that the URI is well-known.
29
+ * For example, certain Jitsi Meet deployments are not conventional but it is
30
+ * possible to translate their URLs into conventional.
31
+ *
32
+ * @param {string} uri - The URI (string) to fix the hier-part of.
33
+ * @private
34
+ * @returns {string}
35
+ */
36
+function _fixURIStringHierPart(uri) {
37
+    // Rewrite the specified URL in order to handle special cases such as
38
+    // hipchat.com and enso.me which do not follow the common pattern of most
39
+    // Jitsi Meet deployments.
40
+
41
+    // hipchat.com
42
+    let regex
43
+        = new RegExp(
44
+            `^${_URI_PROTOCOL_PATTERN}//hipchat\\.com/video/call/`,
45
+            'gi');
46
+    let match = regex.exec(uri);
47
+
48
+    if (!match) {
49
+        // enso.me
50
+        regex
51
+            = new RegExp(
52
+                `^${_URI_PROTOCOL_PATTERN}//enso\\.me/(?:call|meeting)/`,
53
+                'gi');
54
+        match = regex.exec(uri);
55
+    }
56
+    if (match) {
57
+        /* eslint-disable no-param-reassign, prefer-template */
58
+
59
+        uri
60
+            = match[1] /* protocol */
61
+                + '//enso.hipchat.me/'
62
+                + uri.substring(regex.lastIndex); /* room (name) */
63
+
64
+        /* eslint-enable no-param-reassign, prefer-template */
65
+    }
66
+
67
+    return uri;
68
+}
69
+
70
+/**
71
+ * Fixes the scheme part of a specific URI (string) so that it contains a
72
+ * well-known scheme such as HTTP(S). For example, the mobile app implements an
73
+ * app-specific URI scheme in addition to Universal Links. The app-specific
74
+ * scheme may precede or replace the well-known scheme. In such a case, dealing
75
+ * with the app-specific scheme only complicates the logic and it is simpler to
76
+ * get rid of it (by translating the app-specific scheme into a well-known
77
+ * scheme).
78
+ *
79
+ * @param {string} uri - The URI (string) to fix the scheme of.
80
+ * @private
81
+ * @returns {string}
82
+ */
83
+function _fixURIStringScheme(uri: string) {
84
+    const regex = new RegExp(`^${_URI_PROTOCOL_PATTERN}+`, 'gi');
85
+    const match = regex.exec(uri);
86
+
87
+    if (match) {
88
+        // As an implementation convenience, pick up the last scheme and make
89
+        // sure that it is a well-known one.
90
+        let protocol = match[match.length - 1].toLowerCase();
91
+
92
+        if (protocol !== 'http:' && protocol !== 'https:') {
93
+            protocol = 'https:';
94
+        }
95
+
96
+        /* eslint-disable no-param-reassign */
97
+
98
+        uri = uri.substring(regex.lastIndex);
99
+        if (uri.startsWith('//')) {
100
+            // The specified URL was not a room name only, it contained an
101
+            // authority.
102
+            uri = protocol + uri;
103
+        }
104
+
105
+        /* eslint-enable no-param-reassign */
106
+    }
107
+
108
+    return uri;
109
+}
110
+
111
+/**
112
+ * Gets the (Web application) context root defined by a specific location (URI).
113
+ *
114
+ * @param {Object} location - The location (URI) which defines the (Web
115
+ * application) context root.
116
+ * @public
117
+ * @returns {string} - The (Web application) context root defined by the
118
+ * specified {@code location} (URI).
119
+ */
120
+export function getLocationContextRoot(location: Object) {
121
+    const pathname = location.pathname;
122
+    const contextRootEndIndex = pathname.lastIndexOf('/');
123
+
124
+    return (
125
+        contextRootEndIndex === -1
126
+            ? '/'
127
+            : pathname.substring(0, contextRootEndIndex + 1));
128
+}
129
+
130
+/**
131
+ * Parses a specific URI string into an object with the well-known properties of
132
+ * the {@link Location} and/or {@link URL} interfaces implemented by Web
133
+ * browsers. The parsing attempts to be in accord with IETF's RFC 3986.
134
+ *
135
+ * @param {string} str - The URI string to parse.
136
+ * @public
137
+ * @returns {{
138
+ *     hash: string,
139
+ *     host: (string|undefined),
140
+ *     hostname: (string|undefined),
141
+ *     pathname: string,
142
+ *     port: (string|undefined),
143
+ *     protocol: (string|undefined),
144
+ *     search: string
145
+ * }}
146
+ */
147
+export function parseStandardURIString(str: string) {
148
+    /* eslint-disable no-param-reassign */
149
+
150
+    const obj = {};
151
+
152
+    let regex;
153
+    let match;
154
+
155
+    // protocol
156
+    regex = new RegExp(`^${_URI_PROTOCOL_PATTERN}`, 'gi');
157
+    match = regex.exec(str);
158
+    if (match) {
159
+        obj.protocol = match[1].toLowerCase();
160
+        str = str.substring(regex.lastIndex);
161
+    }
162
+
163
+    // authority
164
+    regex = new RegExp(`^${_URI_AUTHORITY_PATTERN}`, 'gi');
165
+    match = regex.exec(str);
166
+    if (match) {
167
+        let authority = match[1].substring(/* // */ 2);
168
+
169
+        str = str.substring(regex.lastIndex);
170
+
171
+        // userinfo
172
+        const userinfoEndIndex = authority.indexOf('@');
173
+
174
+        if (userinfoEndIndex !== -1) {
175
+            authority = authority.substring(userinfoEndIndex + 1);
176
+        }
177
+
178
+        obj.host = authority;
179
+
180
+        // port
181
+        const portBeginIndex = authority.lastIndexOf(':');
182
+
183
+        if (portBeginIndex !== -1) {
184
+            obj.port = authority.substring(portBeginIndex + 1);
185
+            authority = authority.substring(0, portBeginIndex);
186
+        }
187
+
188
+        // hostname
189
+        obj.hostname = authority;
190
+    }
191
+
192
+    // pathname
193
+    regex = new RegExp(`^${_URI_PATH_PATTERN}`, 'gi');
194
+    match = regex.exec(str);
195
+
196
+    let pathname;
197
+
198
+    if (match) {
199
+        pathname = match[1];
200
+        str = str.substring(regex.lastIndex);
201
+    }
202
+    if (pathname) {
203
+        if (!pathname.startsWith('/')) {
204
+            pathname = `/${pathname}`;
205
+        }
206
+    } else {
207
+        pathname = '/';
208
+    }
209
+    obj.pathname = pathname;
210
+
211
+    // query
212
+    if (str.startsWith('?')) {
213
+        let hashBeginIndex = str.indexOf('#', 1);
214
+
215
+        if (hashBeginIndex === -1) {
216
+            hashBeginIndex = str.length;
217
+        }
218
+        obj.search = str.substring(0, hashBeginIndex);
219
+        str = str.substring(hashBeginIndex);
220
+    } else {
221
+        obj.search = ''; // Google Chrome
222
+    }
223
+
224
+    // fragment
225
+    obj.hash = str.startsWith('#') ? str : '';
226
+
227
+    /* eslint-enable no-param-reassign */
228
+
229
+    return obj;
230
+}
231
+
232
+/**
233
+ * Parses a specific URI which (supposedly) references a Jitsi Meet resource
234
+ * (location).
235
+ *
236
+ * @param {(string|undefined)} uri - The URI to parse which (supposedly)
237
+ * references a Jitsi Meet resource (location).
238
+ * @public
239
+ * @returns {{
240
+ *     room: (string|undefined)
241
+ * }}
242
+ */
243
+export function parseURIString(uri: ?string) {
244
+    if (typeof uri !== 'string') {
245
+        return undefined;
246
+    }
247
+
248
+    const obj
249
+        = parseStandardURIString(
250
+            _fixURIStringHierPart(_fixURIStringScheme(uri)));
251
+
252
+    // Add the properties that are specific to a Jitsi Meet resource (location)
253
+    // such as contextRoot, room:
254
+
255
+    // contextRoot
256
+    obj.contextRoot = getLocationContextRoot(obj);
257
+
258
+    // The room (name) is the last component of pathname.
259
+    const { pathname } = obj;
260
+
261
+    obj.room = pathname.substring(pathname.lastIndexOf('/') + 1) || undefined;
262
+
263
+    return obj;
264
+}

Loading…
Cancel
Save