350350 backoffCount : "cly_hc_backoff_count" ,
351351 consecutiveBackoffCount : "cly_hc_consecutive_backoff_count"
352352 } ) ;
353- var SDK_VERSION = "26.1.2 " ;
353+ var SDK_VERSION = "26.1.3 " ;
354354 var SDK_NAME = "javascript_native_web" ;
355355
356356 // Using this on document.referrer would return an array with 17 elements in it. The 12th element (array[11]) would be the path we are looking for. Others would be things like password and such (use https://regex101.com/ to check more)
10921092 }
10931093 }
10941094
1095+ /**
1096+ * Split a URL string into its parts using the shared urlParseRE regex. Kept regex-based
1097+ * (rather than the URL constructor) to preserve IE11 support, and it needs no DOM access.
1098+ * Relative URLs (no scheme/host) return an empty origin and everything in pathname.
1099+ * @memberof Countly._internals
1100+ * @param {String } urlString - URL to parse
1101+ * @returns {Object } object with origin, pathname, search and hash string properties
1102+ */
1103+ function parseUrlParts ( urlString ) {
1104+ var parts = {
1105+ origin : "" ,
1106+ pathname : "" ,
1107+ search : "" ,
1108+ hash : ""
1109+ } ;
1110+ if ( typeof urlString !== "string" ) {
1111+ return parts ;
1112+ }
1113+ var matches = urlParseRE . exec ( urlString ) ;
1114+ if ( ! matches ) {
1115+ return parts ;
1116+ }
1117+ // matches[4] = "protocol:", matches[10] = "host[:port]", matches[13] = path,
1118+ // matches[16] = "?query", matches[17] = "#hash" (see urlParseRE comments in Constants.js)
1119+ if ( matches [ 4 ] && matches [ 10 ] ) {
1120+ parts . origin = matches [ 4 ] + "//" + matches [ 10 ] ;
1121+ }
1122+ parts . pathname = matches [ 13 ] || "" ;
1123+ parts . search = matches [ 16 ] || "" ;
1124+ parts . hash = matches [ 17 ] || "" ;
1125+ return parts ;
1126+ }
1127+
10951128 var _consentTimer = /*#__PURE__*/ new WeakMap ( ) ;
10961129 var _self = /*#__PURE__*/ new WeakMap ( ) ;
10971130 var _global = /*#__PURE__*/ new WeakMap ( ) ;
51045137 // Origin is passed to the popup so that it passes it back in the postMessage event
51055138 // Only web SDK passes origin and web
51065139 url += "&origin=" + passedOrigin ;
5140+ // Pass the path prefix (if any) for reverse proxy scenarios. The server only accepts a
5141+ // same-origin relative path, so we send just the pathname and omit it when there is none.
5142+ var providedPath = "" ;
5143+ if ( _this . url ) {
5144+ providedPath = stripTrailingSlash ( parseUrlParts ( _this . url ) . pathname ) ;
5145+ }
5146+ if ( providedPath ) {
5147+ url += "&provided_url=" + encodeURIComponent ( providedPath ) ;
5148+ }
51075149 url += "&widget_v=web" ;
51085150 var iframe = document . createElement ( "iframe" ) ;
51095151 iframe . src = url ;
57145756 } ) ;
57155757 _classPrivateFieldInitSpec ( this , _displayContent , function ( response ) {
57165758 try {
5759+ // 1. rebase html onto dev provided url so the content page loads from the right path
5760+ // 2. pass the SDK path prefix as provided_url
5761+ var contentUrl = response . html ;
5762+ if ( typeof contentUrl === "string" ) {
5763+ var parts = parseUrlParts ( contentUrl ) ;
5764+ var base = parts . origin + parts . pathname ;
5765+ if ( _this . url && contentUrl . indexOf ( _this . url ) !== 0 ) {
5766+ base = stripTrailingSlash ( _this . url ) + parts . pathname ;
5767+ }
5768+ var search = parts . search ;
5769+ var providedPath = _this . url ? stripTrailingSlash ( parseUrlParts ( _this . url ) . pathname ) : "" ;
5770+ if ( providedPath ) {
5771+ // insert into the query (before any #hash); server ignores values with ':' or '//'
5772+ search += ( search ? "&" : "?" ) + "provided_url=" + encodeURIComponent ( providedPath ) ;
5773+ }
5774+ contentUrl = base + search + parts . hash ;
5775+ _classPrivateFieldGet2 ( _log , _this ) . call ( _this , logLevelEnums . DEBUG , "displayContent, Content iframe URL:[" + contentUrl + "]" ) ;
5776+ }
57175777 var iframe = document . createElement ( "iframe" ) ;
57185778 iframe . id = _classPrivateFieldGet2 ( _contentIframeID , _this ) ;
57195779 // always https in the future
57205780 // response.html = response.html.replace(/http:\/\//g, "https://");
5721- iframe . src = response . html ;
5781+ iframe . src = contentUrl ;
57225782 iframe . style . position = "absolute" ;
5723- if ( response . html . indexOf ( "feedback/survey" ) != - 1 ) {
5783+ if ( contentUrl . indexOf ( "feedback/survey" ) != - 1 ) {
57245784 // for surveys to scroll with the page (nps is not in journeys yet)
57255785 iframe . style . position = "fixed" ;
57265786 }
57425802 }
57435803 } ) ;
57445804 _classPrivateFieldInitSpec ( this , _interpretContentMessage , function ( messageEvent ) {
5745- if ( _this . contentWhitelist . indexOf ( messageEvent . origin ) === - 1 ) {
5805+ // messageEvent.origin is always origin-only (scheme://host[:port]), while whitelist
5806+ // entries (including this.url) may carry a path prefix behind a reverse proxy. Compare
5807+ // by origin so proxied content (served from this.url's origin) is not rejected.
5808+ var isWhitelistedOrigin = Array . isArray ( _this . contentWhitelist ) && _this . contentWhitelist . some ( function ( entry ) {
5809+ return parseUrlParts ( entry ) . origin === messageEvent . origin ;
5810+ } ) ;
5811+ if ( ! isWhitelistedOrigin ) {
57465812 // this.#log(logLevelEnums.ERROR, "interpretContentMessage, Received message from invalid origin");
57475813 // silent ignore
57485814 return ;
74177483 truncateObject : truncateObject ,
74187484 truncateSingleValue : truncateSingleValue ,
74197485 stripTrailingSlash : stripTrailingSlash ,
7486+ parseUrlParts : parseUrlParts ,
74207487 prepareParams : prepareParams ,
74217488 sendXmlHttpRequest : _classPrivateFieldGet2 ( _sendXmlHttpRequest , this ) ,
74227489 isResponseValid : _classPrivateFieldGet2 ( _isResponseValid , this ) ,
78897956
78907957 Object . defineProperty ( exports , '__esModule' , { value : true } ) ;
78917958
7892- } ) ) ;
7959+ } ) ) ;
0 commit comments