This repository has been archived on 2026-05-25. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
komuniki-jitsi-ui/jitsi-meet/libs/do_external_connect.min.map
Antoine Ouvrard d3277d6563 initial commit
2020-11-23 10:28:32 +01:00

1 line
33 KiB
Plaintext

{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./react/features/base/util/parseURLParams.js","webpack:///./react/features/base/util/helpers.js","webpack:///./react/features/base/util/uri.js","webpack:///./react/features/base/util/strings.web.js","webpack:///./connection_optimization/do_external_connect.js","webpack:///./react/features/base/config/getRoomName.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","parseURLParams","url","dontParse","source","paramStr","search","hash","params","paramParts","substr","split","length","firstParam","startsWith","forEach","part","param","decoded","decodeURIComponent","replace","undefined","JSON","parse","e","msg","console","error","window","onerror","reportError","String","getBackendSafeRoomName","room","normalize","toLowerCase","encodeURIComponent","createConnectionExternally","location","config","websocket","externalConnectUrl","isRecorder","roomName","path","pathname","substring","lastIndexOf","getRoomName","token","jwt","connectionInfo","XMPPAttachInfo","status","data","checkForConnectHandlerAndConnect","errorCallback","APP","connect","handler","warn"],"mappings":"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","file":"do_external_connect.min.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/libs/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","/* @flow */\n\nimport { reportError } from './helpers';\n\n/**\n * Parses the query/search or fragment/hash parameters out of a specific URL and\n * returns them as a JS object.\n *\n * @param {URL} url - The URL to parse.\n * @param {boolean} dontParse - If falsy, some transformations (for parsing the\n * value as JSON) will be executed.\n * @param {string} source - If {@code 'search'}, the parameters will parsed out\n * of {@code url.search}; otherwise, out of {@code url.hash}.\n * @returns {Object}\n */\nexport function parseURLParams(\n url: URL,\n dontParse: boolean = false,\n source: string = 'hash'): Object {\n const paramStr = source === 'search' ? url.search : url.hash;\n const params = {};\n const paramParts = (paramStr && paramStr.substr(1).split('&')) || [];\n\n // Detect and ignore hash params for hash routers.\n if (source === 'hash' && paramParts.length === 1) {\n const firstParam = paramParts[0];\n\n if (firstParam.startsWith('/') && firstParam.split('&').length === 1) {\n return params;\n }\n }\n\n paramParts.forEach(part => {\n const param = part.split('=');\n const key = param[0];\n\n if (!key) {\n return;\n }\n\n let value;\n\n try {\n value = param[1];\n\n if (!dontParse) {\n const decoded = decodeURIComponent(value).replace(/\\\\&/, '&');\n\n value = decoded === 'undefined' ? undefined : JSON.parse(decoded);\n }\n } catch (e) {\n reportError(\n e, `Failed to parse URL parameter value: ${String(value)}`);\n\n return;\n }\n params[key] = value;\n });\n\n return params;\n}\n","// @flow\n\n/**\n * A helper function that behaves similar to Object.assign, but only reassigns a\n * property in target if it's defined in source.\n *\n * @param {Object} target - The target object to assign the values into.\n * @param {Object} source - The source object.\n * @returns {Object}\n */\nexport function assignIfDefined(target: Object, source: Object) {\n const to = Object(target);\n\n for (const nextKey in source) {\n if (source.hasOwnProperty(nextKey)) {\n const value = source[nextKey];\n\n if (typeof value !== 'undefined') {\n to[nextKey] = value;\n }\n }\n }\n\n return to;\n}\n\n/**\n * Tries to copy a given text to the clipboard.\n * Returns true if the action succeeds.\n *\n * @param {string} textToCopy - Text to be copied.\n * @returns {boolean}\n */\nexport function copyText(textToCopy: string) {\n const fakeTextArea = document.createElement('textarea');\n let result;\n\n // $FlowFixMe\n document.body.appendChild(fakeTextArea);\n fakeTextArea.value = textToCopy;\n fakeTextArea.select();\n\n try {\n result = document.execCommand('copy');\n } catch (err) {\n result = false;\n }\n\n // $FlowFixMe\n document.body.removeChild(fakeTextArea);\n\n return result;\n}\n\n/**\n * Creates a deferred object.\n *\n * @returns {{promise, resolve, reject}}\n */\nexport function createDeferred(): Object {\n const deferred = {};\n\n deferred.promise = new Promise((resolve, reject) => {\n deferred.resolve = resolve;\n deferred.reject = reject;\n });\n\n return deferred;\n}\n\nconst MATCH_OPERATOR_REGEXP = /[|\\\\{}()[\\]^$+*?.-]/g;\n\n/**\n * Escape RegExp special characters.\n *\n * Based on https://github.com/sindresorhus/escape-string-regexp.\n *\n * @param {string} s - The regexp string to escape.\n * @returns {string}\n */\nexport function escapeRegexp(s: string) {\n if (typeof s !== 'string') {\n throw new TypeError('Expected a string');\n }\n\n return s.replace(MATCH_OPERATOR_REGEXP, '\\\\$&');\n}\n\n/**\n * Returns the base URL of the app.\n *\n * @param {Object} w - Window object to use instead of the built in one.\n * @returns {string}\n */\nexport function getBaseUrl(w: Object = window) {\n const doc = w.document;\n const base = doc.querySelector('base');\n\n if (base && base.href) {\n return base.href;\n }\n\n const { protocol, host } = w.location;\n\n return `${protocol}//${host}`;\n}\n\n/**\n * Returns the namespace for all global variables, functions, etc that we need.\n *\n * @returns {Object} The namespace.\n *\n * NOTE: After React-ifying everything this should be the only global.\n */\nexport function getJitsiMeetGlobalNS() {\n if (!window.JitsiMeetJS) {\n window.JitsiMeetJS = {};\n }\n\n if (!window.JitsiMeetJS.app) {\n window.JitsiMeetJS.app = {};\n }\n\n return window.JitsiMeetJS.app;\n}\n\n/**\n * Prints the error and reports it to the global error handler.\n *\n * @param {Error} e - The error object.\n * @param {string} msg - A custom message to print in addition to the error.\n * @returns {void}\n */\nexport function reportError(e: Object, msg: string = '') {\n console.error(msg, e);\n window.onerror && window.onerror(msg, null, null, null, e);\n}\n","// @flow\n\nimport { parseURLParams } from './parseURLParams';\nimport { normalizeNFKC } from './strings';\n\n/**\n * The app linking scheme.\n * TODO: This should be read from the manifest files later.\n */\nexport const APP_LINK_SCHEME = 'org.jitsi.meet:';\n\n/**\n * A list of characters to be excluded/removed from the room component/segment\n * of a conference/meeting URI/URL. The list is based on RFC 3986 and the jxmpp\n * library utilized by jicofo.\n */\nconst _ROOM_EXCLUDE_PATTERN = '[\\\\:\\\\?#\\\\[\\\\]@!$&\\'()*+,;=></\"]';\n\n/**\n * The {@link RegExp} pattern of the authority of a URI.\n *\n * @private\n * @type {string}\n */\nconst _URI_AUTHORITY_PATTERN = '(//[^/?#]+)';\n\n/**\n * The {@link RegExp} pattern of the path of a URI.\n *\n * @private\n * @type {string}\n */\nconst _URI_PATH_PATTERN = '([^?#]*)';\n\n/**\n * The {@link RegExp} pattern of the protocol of a URI.\n *\n * FIXME: The URL class exposed by JavaScript will not include the colon in\n * the protocol field. Also in other places (at the time of this writing:\n * the DeepLinkingMobilePage.js) the APP_LINK_SCHEME does not include\n * the double dots, so things are inconsistent.\n *\n * @type {string}\n */\nexport const URI_PROTOCOL_PATTERN = '^([a-z][a-z0-9\\\\.\\\\+-]*:)';\n\n/**\n * Excludes/removes certain characters from a specific room (name) which are\n * incompatible with Jitsi Meet on the client and/or server sides.\n *\n * @param {?string} room - The room (name) to fix.\n * @private\n * @returns {?string}\n */\nfunction _fixRoom(room: ?string) {\n return room\n ? room.replace(new RegExp(_ROOM_EXCLUDE_PATTERN, 'g'), '')\n : room;\n}\n\n/**\n * Fixes the scheme part of a specific URI (string) so that it contains a\n * well-known scheme such as HTTP(S). For example, the mobile app implements an\n * app-specific URI scheme in addition to Universal Links. The app-specific\n * scheme may precede or replace the well-known scheme. In such a case, dealing\n * with the app-specific scheme only complicates the logic and it is simpler to\n * get rid of it (by translating the app-specific scheme into a well-known\n * scheme).\n *\n * @param {string} uri - The URI (string) to fix the scheme of.\n * @private\n * @returns {string}\n */\nfunction _fixURIStringScheme(uri: string) {\n const regex = new RegExp(`${URI_PROTOCOL_PATTERN}+`, 'gi');\n const match: Array<string> | null = regex.exec(uri);\n\n if (match) {\n // As an implementation convenience, pick up the last scheme and make\n // sure that it is a well-known one.\n let protocol = match[match.length - 1].toLowerCase();\n\n if (protocol !== 'http:' && protocol !== 'https:') {\n protocol = 'https:';\n }\n\n /* eslint-disable no-param-reassign */\n\n uri = uri.substring(regex.lastIndex);\n if (uri.startsWith('//')) {\n // The specified URL was not a room name only, it contained an\n // authority.\n uri = protocol + uri;\n }\n\n /* eslint-enable no-param-reassign */\n }\n\n return uri;\n}\n\n/**\n * Converts a path to a backend-safe format, by splitting the path '/' processing each part.\n * Properly lowercased and url encoded.\n *\n * @param {string?} path - The path to convert.\n * @returns {string?}\n */\nexport function getBackendSafePath(path: ?string): ?string {\n if (!path) {\n return path;\n }\n\n return path\n .split('/')\n .map(getBackendSafeRoomName)\n .join('/');\n}\n\n/**\n * Converts a room name to a backend-safe format. Properly lowercased and url encoded.\n *\n * @param {string?} room - The room name to convert.\n * @returns {string?}\n */\nexport function getBackendSafeRoomName(room: ?string): ?string {\n if (!room) {\n return room;\n }\n\n /* eslint-disable no-param-reassign */\n try {\n // We do not know if we get an already encoded string at this point\n // as different platforms do it differently, but we need a decoded one\n // for sure. However since decoding a non-encoded string is a noop, we're safe\n // doing it here.\n room = decodeURIComponent(room);\n } catch (e) {\n // This can happen though if we get an unencoded string and it contains\n // some characters that look like an encoded entity, but it's not.\n // But in this case we're fine goin on...\n }\n\n // Normalize the character set.\n room = normalizeNFKC(room);\n\n // Only decoded and normalized strings can be lowercased properly.\n room = room.toLowerCase();\n\n // But we still need to (re)encode it.\n room = encodeURIComponent(room);\n /* eslint-enable no-param-reassign */\n\n // Unfortunately we still need to lowercase it, because encoding a string will\n // add some uppercase characters, but some backend services\n // expect it to be full lowercase. However lowercasing an encoded string\n // doesn't change the string value.\n return room.toLowerCase();\n}\n\n/**\n * Gets the (Web application) context root defined by a specific location (URI).\n *\n * @param {Object} location - The location (URI) which defines the (Web\n * application) context root.\n * @public\n * @returns {string} - The (Web application) context root defined by the\n * specified {@code location} (URI).\n */\nexport function getLocationContextRoot({ pathname }: { pathname: string }) {\n const contextRootEndIndex = pathname.lastIndexOf('/');\n\n return (\n contextRootEndIndex === -1\n ? '/'\n : pathname.substring(0, contextRootEndIndex + 1));\n}\n\n/**\n * Constructs a new {@code Array} with URL parameter {@code String}s out of a\n * specific {@code Object}.\n *\n * @param {Object} obj - The {@code Object} to turn into URL parameter\n * {@code String}s.\n * @returns {Array<string>} The {@code Array} with URL parameter {@code String}s\n * constructed out of the specified {@code obj}.\n */\nfunction _objectToURLParamsArray(obj = {}) {\n const params = [];\n\n for (const key in obj) { // eslint-disable-line guard-for-in\n try {\n params.push(\n `${key}=${encodeURIComponent(JSON.stringify(obj[key]))}`);\n } catch (e) {\n console.warn(`Error encoding ${key}: ${e}`);\n }\n }\n\n return params;\n}\n\n/**\n * Parses a specific URI string into an object with the well-known properties of\n * the {@link Location} and/or {@link URL} interfaces implemented by Web\n * browsers. The parsing attempts to be in accord with IETF's RFC 3986.\n *\n * @param {string} str - The URI string to parse.\n * @public\n * @returns {{\n * hash: string,\n * host: (string|undefined),\n * hostname: (string|undefined),\n * pathname: string,\n * port: (string|undefined),\n * protocol: (string|undefined),\n * search: string\n * }}\n */\nexport function parseStandardURIString(str: string) {\n /* eslint-disable no-param-reassign */\n\n const obj: Object = {\n toString: _standardURIToString\n };\n\n let regex;\n let match: Array<string> | null;\n\n // XXX A URI string as defined by RFC 3986 does not contain any whitespace.\n // Usually, a browser will have already encoded any whitespace. In order to\n // avoid potential later problems related to whitespace in URI, strip any\n // whitespace. Anyway, the Jitsi Meet app is not known to utilize unencoded\n // whitespace so the stripping is deemed safe.\n str = str.replace(/\\s/g, '');\n\n // protocol\n regex = new RegExp(URI_PROTOCOL_PATTERN, 'gi');\n match = regex.exec(str);\n if (match) {\n obj.protocol = match[1].toLowerCase();\n str = str.substring(regex.lastIndex);\n }\n\n // authority\n regex = new RegExp(`^${_URI_AUTHORITY_PATTERN}`, 'gi');\n match = regex.exec(str);\n if (match) {\n let authority: string = match[1].substring(/* // */ 2);\n\n str = str.substring(regex.lastIndex);\n\n // userinfo\n const userinfoEndIndex = authority.indexOf('@');\n\n if (userinfoEndIndex !== -1) {\n authority = authority.substring(userinfoEndIndex + 1);\n }\n\n obj.host = authority;\n\n // port\n const portBeginIndex = authority.lastIndexOf(':');\n\n if (portBeginIndex !== -1) {\n obj.port = authority.substring(portBeginIndex + 1);\n authority = authority.substring(0, portBeginIndex);\n }\n\n // hostname\n obj.hostname = authority;\n }\n\n // pathname\n regex = new RegExp(`^${_URI_PATH_PATTERN}`, 'gi');\n match = regex.exec(str);\n\n let pathname: ?string;\n\n if (match) {\n pathname = match[1];\n str = str.substring(regex.lastIndex);\n }\n if (pathname) {\n pathname.startsWith('/') || (pathname = `/${pathname}`);\n } else {\n pathname = '/';\n }\n obj.pathname = pathname;\n\n // query\n if (str.startsWith('?')) {\n let hashBeginIndex = str.indexOf('#', 1);\n\n if (hashBeginIndex === -1) {\n hashBeginIndex = str.length;\n }\n obj.search = str.substring(0, hashBeginIndex);\n str = str.substring(hashBeginIndex);\n } else {\n obj.search = ''; // Google Chrome\n }\n\n // fragment\n obj.hash = str.startsWith('#') ? str : '';\n\n /* eslint-enable no-param-reassign */\n\n return obj;\n}\n\n/**\n * Parses a specific URI which (supposedly) references a Jitsi Meet resource\n * (location).\n *\n * @param {(string|undefined)} uri - The URI to parse which (supposedly)\n * references a Jitsi Meet resource (location).\n * @public\n * @returns {{\n * contextRoot: string,\n * hash: string,\n * host: string,\n * hostname: string,\n * pathname: string,\n * port: string,\n * protocol: string,\n * room: (string|undefined),\n * search: string\n * }}\n */\nexport function parseURIString(uri: ?string) {\n if (typeof uri !== 'string') {\n return undefined;\n }\n\n const obj = parseStandardURIString(_fixURIStringScheme(uri));\n\n // Add the properties that are specific to a Jitsi Meet resource (location)\n // such as contextRoot, room:\n\n // contextRoot\n obj.contextRoot = getLocationContextRoot(obj);\n\n // The room (name) is the last component/segment of pathname.\n const { pathname } = obj;\n\n // XXX While the components/segments of pathname are URI encoded, Jitsi Meet\n // on the client and/or server sides still don't support certain characters.\n const contextRootEndIndex = pathname.lastIndexOf('/');\n let room = pathname.substring(contextRootEndIndex + 1) || undefined;\n\n if (room) {\n const fixedRoom = _fixRoom(room);\n\n if (fixedRoom !== room) {\n room = fixedRoom;\n\n // XXX Drive fixedRoom into pathname (because room is derived from\n // pathname).\n obj.pathname\n = pathname.substring(0, contextRootEndIndex + 1) + (room || '');\n }\n }\n obj.room = room;\n\n return obj;\n}\n\n/**\n * Implements {@code href} and {@code toString} for the {@code Object} returned\n * by {@link #parseStandardURIString}.\n *\n * @param {Object} [thiz] - An {@code Object} returned by\n * {@code #parseStandardURIString} if any; otherwise, it is presumed that the\n * function is invoked on such an instance.\n * @returns {string}\n */\nfunction _standardURIToString(thiz: ?Object) {\n // eslint-disable-next-line no-invalid-this\n const { hash, host, pathname, protocol, search } = thiz || this;\n let str = '';\n\n protocol && (str += protocol);\n\n // TODO userinfo\n\n host && (str += `//${host}`);\n str += pathname || '/';\n search && (str += search);\n hash && (str += hash);\n\n return str;\n}\n\n/**\n * Sometimes we receive strings that we don't know if already percent-encoded, or not, due to the\n * various sources we get URLs or room names. This function encapsulates the decoding in a safe way.\n *\n * @param {string} text - The text to decode.\n * @returns {string}\n */\nexport function safeDecodeURIComponent(text: string) {\n try {\n return decodeURIComponent(text);\n } catch (e) {\n // The text wasn't encoded.\n }\n\n return text;\n}\n\n/**\n * Attempts to return a {@code String} representation of a specific\n * {@code Object} which is supposed to represent a URL. Obviously, if a\n * {@code String} is specified, it is returned. If a {@code URL} is specified,\n * its {@code URL#href} is returned. Additionally, an {@code Object} similar to\n * the one accepted by the constructor of Web's ExternalAPI is supported on both\n * mobile/React Native and Web/React.\n *\n * @param {Object|string} obj - The URL to return a {@code String}\n * representation of.\n * @returns {string} - A {@code String} representation of the specified\n * {@code obj} which is supposed to represent a URL.\n */\nexport function toURLString(obj: ?(Object | string)): ?string {\n let str;\n\n switch (typeof obj) {\n case 'object':\n if (obj) {\n if (obj instanceof URL) {\n str = obj.href;\n } else {\n str = urlObjectToString(obj);\n }\n }\n break;\n\n case 'string':\n str = String(obj);\n break;\n }\n\n return str;\n}\n\n/**\n * Attempts to return a {@code String} representation of a specific\n * {@code Object} similar to the one accepted by the constructor\n * of Web's ExternalAPI.\n *\n * @param {Object} o - The URL to return a {@code String} representation of.\n * @returns {string} - A {@code String} representation of the specified\n * {@code Object}.\n */\nexport function urlObjectToString(o: Object): ?string {\n // First normalize the given url. It come as o.url or split into o.serverURL\n // and o.room.\n let tmp;\n\n if (o.serverURL && o.room) {\n tmp = new URL(o.room, o.serverURL).toString();\n } else if (o.room) {\n tmp = o.room;\n } else {\n tmp = o.url || '';\n }\n\n const url = parseStandardURIString(_fixURIStringScheme(tmp));\n\n // protocol\n if (!url.protocol) {\n let protocol: ?string = o.protocol || o.scheme;\n\n if (protocol) {\n // Protocol is supposed to be the scheme and the final ':'. Anyway,\n // do not make a fuss if the final ':' is not there.\n protocol.endsWith(':') || (protocol += ':');\n url.protocol = protocol;\n }\n }\n\n // authority & pathname\n let { pathname } = url;\n\n if (!url.host) {\n // Web's ExternalAPI domain\n //\n // It may be host/hostname and pathname with the latter denoting the\n // tenant.\n const domain: ?string = o.domain || o.host || o.hostname;\n\n if (domain) {\n const { host, hostname, pathname: contextRoot, port }\n = parseStandardURIString(\n\n // XXX The value of domain in supposed to be host/hostname\n // and, optionally, pathname. Make sure it is not taken for\n // a pathname only.\n _fixURIStringScheme(`${APP_LINK_SCHEME}//${domain}`));\n\n // authority\n if (host) {\n url.host = host;\n url.hostname = hostname;\n url.port = port;\n }\n\n // pathname\n pathname === '/' && contextRoot !== '/' && (pathname = contextRoot);\n }\n }\n\n // pathname\n\n // Web's ExternalAPI roomName\n const room = o.roomName || o.room;\n\n if (room\n && (url.pathname.endsWith('/')\n || !url.pathname.endsWith(`/${room}`))) {\n pathname.endsWith('/') || (pathname += '/');\n pathname += room;\n }\n\n url.pathname = pathname;\n\n // query/search\n\n // Web's ExternalAPI jwt\n const { jwt } = o;\n\n if (jwt) {\n let { search } = url;\n\n if (search.indexOf('?jwt=') === -1 && search.indexOf('&jwt=') === -1) {\n search.startsWith('?') || (search = `?${search}`);\n search.length === 1 || (search += '&');\n search += `jwt=${jwt}`;\n\n url.search = search;\n }\n }\n\n // fragment/hash\n\n let { hash } = url;\n\n for (const urlPrefix of [ 'config', 'interfaceConfig', 'devices', 'userInfo', 'appData' ]) {\n const urlParamsArray\n = _objectToURLParamsArray(\n o[`${urlPrefix}Overwrite`]\n || o[urlPrefix]\n || o[`${urlPrefix}Override`]);\n\n if (urlParamsArray.length) {\n let urlParamsString\n = `${urlPrefix}.${urlParamsArray.join(`&${urlPrefix}.`)}`;\n\n if (hash.length) {\n urlParamsString = `&${urlParamsString}`;\n } else {\n hash = '#';\n }\n hash += urlParamsString;\n }\n }\n\n url.hash = hash;\n\n return url.toString() || undefined;\n}\n\n/**\n * Adds hash params to URL.\n *\n * @param {URL} url - The URL.\n * @param {Object} hashParamsToAdd - A map with the parameters to be set.\n * @returns {URL} - The new URL.\n */\nexport function addHashParamsToURL(url: URL, hashParamsToAdd: Object = {}) {\n const params = parseURLParams(url);\n const urlParamsArray = _objectToURLParamsArray({\n ...params,\n ...hashParamsToAdd\n });\n\n if (urlParamsArray.length) {\n url.hash = `#${urlParamsArray.join('&')}`;\n }\n\n return url;\n}\n\n/**\n * Returns the decoded URI.\n *\n * @param {string} uri - The URI to decode.\n * @returns {string}\n */\nexport function getDecodedURI(uri: string) {\n return decodeURI(uri.replace(/^https?:\\/\\//i, ''));\n}\n","// @flow\n\n/**\n * Applies NFKC normalization to the given text.\n *\n * @param {string} text - The text that needs to be normalized.\n * @returns {string} - The normalized text.\n */\nexport function normalizeNFKC(text: string) {\n return text.normalize('NFKC');\n}\n","/* global config, createConnectionExternally */\n\nimport getRoomName from '../react/features/base/config/getRoomName';\nimport { parseURLParams } from '../react/features/base/util/parseURLParams';\n\n/**\n * Implements external connect using createConnectionExternally function defined\n * in external_connect.js for Jitsi Meet. Parses the room name and JSON Web\n * Token (JWT) from the URL and executes createConnectionExternally.\n *\n * NOTE: If you are using lib-jitsi-meet without Jitsi Meet, you should use this\n * file as reference only because the implementation is Jitsi Meet-specific.\n *\n * NOTE: For optimal results this file should be included right after\n * external_connect.js.\n */\n\nif (typeof createConnectionExternally === 'function') {\n // URL params have higher priority than config params.\n // Do not use external connect if websocket is enabled.\n let url\n = parseURLParams(window.location, true, 'hash')[\n 'config.externalConnectUrl']\n || config.websocket ? undefined : config.externalConnectUrl;\n const isRecorder\n = parseURLParams(window.location, true, 'hash')['config.iAmRecorder'];\n\n let roomName;\n\n if (url && (roomName = getRoomName()) && !isRecorder) {\n url += `?room=${roomName}`;\n\n const token = parseURLParams(window.location, true, 'search').jwt;\n\n if (token) {\n url += `&token=${token}`;\n }\n\n createConnectionExternally(\n url,\n connectionInfo => {\n // Sets that global variable to be used later by connect method\n // in connection.js.\n window.XMPPAttachInfo = {\n status: 'success',\n data: connectionInfo\n };\n checkForConnectHandlerAndConnect();\n },\n errorCallback);\n } else {\n errorCallback();\n }\n} else {\n errorCallback();\n}\n\n/**\n * Check if connect from connection.js was executed and executes the handler\n * that is going to finish the connect work.\n *\n * @returns {void}\n */\nfunction checkForConnectHandlerAndConnect() {\n window.APP\n && window.APP.connect.status === 'ready'\n && window.APP.connect.handler();\n}\n\n/**\n * Implements a callback to be invoked if anything goes wrong.\n *\n * @param {Error} error - The specifics of what went wrong.\n * @returns {void}\n */\nfunction errorCallback(error) {\n // The value of error is undefined if external connect is disabled.\n error && console.warn(error);\n\n // Sets that global variable to be used later by connect method in\n // connection.js.\n window.XMPPAttachInfo = {\n status: 'error'\n };\n checkForConnectHandlerAndConnect();\n}\n","// @flow\n\nimport { getBackendSafeRoomName } from '../util';\n\n/**\n * Builds and returns the room name.\n *\n * @returns {string}\n */\nexport default function getRoomName(): ?string {\n const path = window.location.pathname;\n\n // The last non-directory component of the path (name) is the room.\n const roomName = path.substring(path.lastIndexOf('/') + 1) || undefined;\n\n return getBackendSafeRoomName(roomName);\n}\n"],"sourceRoot":""}