2019-01-23 11:33:34 +00:00
define ( [ 'events' ] , function ( events ) {
2019-01-10 15:39:37 +03:00
'use strict' ;
// LinkParser
//
// https://github.com/ravisorg/LinkParser
//
2019-11-23 00:29:38 +09:00
// Locate and extract almost any URL within a string. Handles protocol-less domains, IPv4 and
2019-01-10 15:39:37 +03:00
// IPv6, unrecognised TLDs, and more.
//
// This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
// http://creativecommons.org/licenses/by-sa/4.0/
( function ( ) {
// Original URL regex from the Android android.text.util.Linkify function, found here:
// http://stackoverflow.com/a/19696443
2019-11-23 00:29:38 +09:00
//
// However there were problems with it, most probably related to the fact it was
2019-01-10 15:39:37 +03:00
// written in 2007, and it's been highly modified.
2019-11-23 00:29:38 +09:00
//
// 1) I didn't like the fact that it was tied to specific TLDs, since new ones
2019-01-10 15:39:37 +03:00
// are being added all the time it wouldn't be reasonable to expect developer to
// be continually updating their regular expressions.
2019-11-23 00:29:38 +09:00
//
// 2) It didn't allow unicode characters in the domains which are now allowed in
2019-01-10 15:39:37 +03:00
// many languages, (including some IDN TLDs). Again these are constantly being
// added to and it doesn't seem reasonable to hard-code them. Note this ended up
// not being possible in standard JS due to the way it handles multibyte strings.
// It is possible using XRegExp, however a big performance hit results. Disabled
// for now.
2019-11-23 00:29:38 +09:00
//
2019-01-10 15:39:37 +03:00
// 3) It didn't allow for IPv6 hostnames
// IPv6 regex from http://stackoverflow.com/a/17871737
//
// 4) It was very poorly commented
2019-11-23 00:29:38 +09:00
//
2019-01-10 15:39:37 +03:00
// 5) It wasn't as smart as it could have been about what should be part of a
// URL and what should be part of human language.
var protocols = "(?:(?:http|https|rtsp|ftp):\\/\\/)" ;
var credentials = "(?:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,64}" // username (1-64 normal or url escaped characters)
+ "(?:\\:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,25})?" // followed by optional password (: + 1-25 normal or url escaped characters)
+ "\\@)" ;
// IPv6 Regex http://forums.intermapper.com/viewtopic.php?t=452
// by Dartware, LLC is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License
// http://intermapper.com/
var ipv6 = "("
+ "(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))"
+ "|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))"
+ "|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))"
+ "|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
+ "|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
+ "|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
+ "|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
+ "|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
+ ")(%.+)?" ;
var ipv4 = "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\."
+ "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\."
+ "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\."
+ "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])" ;
// This would have been a lot cleaner if JS RegExp supported conditionals...
var linkRegExpString =
// begin match for protocol / username / password / host
"(?:"
// ============================
// If we have a recognized protocol at the beginning of the URL, we're
// more relaxed about what we accept, because we assume the user wants
// this to be a URL, and we're not accidentally matching human language
+ protocols + "?"
// optional username:password@
+ credentials + "?"
// IP address (both v4 and v6)
+ "(?:"
// IPv6
+ ipv6
// IPv4
+ "|" + ipv4
+ ")"
// end match for protocol / username / password / host
+ ")"
// optional port number
+ "(?:\\:\\d{1,5})?"
// plus optional path and query params (no unicode allowed here?)
+ "(?:"
+ "\\/(?:"
// some characters we'll accept because it's unlikely human language
// would use them after a URL unless they were part of the url
+ "(?:[a-z0-9\\/\\@\\&\\#\\~\\*\\_\\-\\+])"
+ "|(?:\\%[a-f0-9]{2})"
// some characters are much more likely to be used AFTER a url and
// were not intended to be included in the url itself. Mostly end
2019-11-23 00:29:38 +09:00
// of sentence type things. It's also likely that the URL would
// still work if any of these characters were missing from the end
2019-01-10 15:39:37 +03:00
// because we parsed it incorrectly. For these characters to be accepted
// they must be followed by another character that we're reasonably
// sure is part of the url
+ "|(?:[\\;\\?\\:\\.\\!\\'\\(\\)\\,\\=]+(?=(?:[a-z0-9\\/\\@\\&\\#\\~\\*\\_\\-\\+])|(?:\\%[a-f0-9]{2})))"
+ ")*"
+ "|\\b|\$"
+ ")" ;
// regex = XRegExp(regex,'gi');
var linkRegExp = RegExp ( linkRegExpString , 'gi' ) ;
var protocolRegExp = RegExp ( '^' + protocols , 'i' ) ;
// if url doesn't begin with a known protocol, add http by default
function ensureProtocol ( url ) {
if ( ! url . match ( protocolRegExp ) ) {
url = "http://" + url ;
}
return url ;
}
// look for links in the text
var LinkParser = {
parse : function ( text ) {
var links = [ ] ;
var match ;
while ( match = linkRegExp . exec ( text ) ) {
2020-02-16 03:44:43 +01:00
// console.debug(matches);
2019-01-10 15:39:37 +03:00
var txt = match [ 0 ] ;
var pos = match . index ;
var len = txt . length ;
var url = ensureProtocol ( text ) ;
links . push ( { 'pos' : pos , 'text' : txt , 'len' : len , 'url' : url } ) ;
}
return links ;
}
} ;
window . LinkParser = LinkParser ;
} ) ( ) ;
var cache = { } ;
2018-10-23 01:05:09 +03:00
function isValidIpAddress ( address ) {
2019-01-10 15:39:37 +03:00
var links = LinkParser . parse ( address ) ;
return links . length == 1 ;
2018-10-23 01:05:09 +03:00
}
function isLocalIpAddress ( address ) {
2019-01-10 15:39:37 +03:00
address = address . toLowerCase ( ) ;
if ( address . indexOf ( '127.0.0.1' ) !== - 1 ) {
return true ;
}
if ( address . indexOf ( 'localhost' ) !== - 1 ) {
return true ;
}
return false ;
2018-10-23 01:05:09 +03:00
}
function getServerAddress ( apiClient ) {
2019-01-10 15:39:37 +03:00
2018-10-23 01:05:09 +03:00
var serverAddress = apiClient . serverAddress ( ) ;
2019-01-10 15:39:37 +03:00
if ( isValidIpAddress ( serverAddress ) && ! isLocalIpAddress ( serverAddress ) ) {
return Promise . resolve ( serverAddress ) ;
}
2018-10-23 01:05:09 +03:00
var cachedValue = getCachedValue ( serverAddress ) ;
2019-01-10 15:39:37 +03:00
if ( cachedValue ) {
return Promise . resolve ( cachedValue ) ;
}
return apiClient . getEndpointInfo ( ) . then ( function ( endpoint ) {
if ( endpoint . IsInNetwork ) {
return apiClient . getPublicSystemInfo ( ) . then ( function ( info ) {
2019-04-01 16:07:56 +02:00
var localAddress = info . LocalAddress
if ( ! localAddress ) {
2020-02-16 03:44:43 +01:00
console . debug ( "No valid local address returned, defaulting to external one" )
2019-04-01 16:07:56 +02:00
localAddress = serverAddress ;
}
addToCache ( serverAddress , localAddress ) ;
return localAddress ;
2019-01-10 15:39:37 +03:00
} ) ;
} else {
addToCache ( serverAddress , serverAddress ) ;
return serverAddress ;
}
} ) ;
2018-10-23 01:05:09 +03:00
}
function clearCache ( ) {
2019-01-10 15:39:37 +03:00
cache = { } ;
2018-10-23 01:05:09 +03:00
}
function addToCache ( key , value ) {
cache [ key ] = {
value : value ,
2019-01-10 15:39:37 +03:00
time : new Date ( ) . getTime ( )
} ;
2018-10-23 01:05:09 +03:00
}
function getCachedValue ( key ) {
2019-01-10 15:39:37 +03:00
2018-10-23 01:05:09 +03:00
var obj = cache [ key ] ;
2019-01-10 15:39:37 +03:00
if ( obj && ( new Date ( ) . getTime ( ) - obj . time ) < 180000 ) {
return obj . value ;
2018-10-23 01:05:09 +03:00
}
2019-01-10 15:39:37 +03:00
return null ;
2018-10-23 01:05:09 +03:00
}
2019-01-10 15:39:37 +03:00
events . on ( ConnectionManager , 'localusersignedin' , clearCache ) ;
events . on ( ConnectionManager , 'localusersignedout' , clearCache ) ;
return {
getServerAddress : getServerAddress
} ;
2018-10-23 01:05:09 +03:00
} ) ;