PageSourceSearch

https://www.e-chinalife.com/jw/csrf

js e-chinalife.com collected 2026-09-24 20:18:59 UTC 33,993 bytes, 783 lines download raw bytes

1/*
2 * The OWASP CSRFGuard Project, BSD License
3 * Copyright (c) 2011, Eric Sheridan ([email protected])
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 *     1. Redistributions of source code must retain the above copyright notice,
10 *        this list of conditions and the following disclaimer.
11 *     2. Redistributions in binary form must reproduce the above copyright
12 *        notice, this list of conditions and the following disclaimer in the
13 *        documentation and/or other materials provided with the distribution.
14 *     3. Neither the name of OWASP nor the names of its contributors may be used
15 *        to endorse or promote products derived from this software without specific
16 *        prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/**
31 * Issue 92: boolean check to avoid running the function multiple times.
32 * Happens if the file is included multiple times which results in
33 * Maximum call stack size exceeded
34 */
35var owaspCSRFGuardScriptHasLoaded = owaspCSRFGuardScriptHasLoaded || {};
36if (owaspCSRFGuardScriptHasLoaded !== true) {
37    (function () {
38        owaspCSRFGuardScriptHasLoaded = true;
39
40        /**
41         * Code to ensure our event always gets triggered when the DOM is updated.
42         * @param obj
43         * @param type
44         * @param fn
45         * @source http://www.dustindiaz.com/rock-solid-addevent/
46         */
47        function addEvent(obj, type, fn) {
48            if (obj.addEventListener) {
49                obj.addEventListener(type, fn, false);
50                EventCache.add(obj, type, fn);
51            } else if (obj.attachEvent) {
52                obj['e' + type + fn] = fn;
53                obj[type + fn] = function () {
54                    obj['e' + type + fn](window.event);
55                };
56                obj.attachEvent('on' + type, obj[type + fn]);
57                EventCache.add(obj, type, fn);
58            } else {
59                obj['on' + type] = obj['e' + type + fn];
60            }
61        }
62
63        var EventCache = function () {
64            var listEvents = [];
65            return {
66                listEvents: listEvents,
67                add: function (node, sEventName, fHandler) {
68                    listEvents.push(arguments);
69                },
70                flush: function () {
71                    var i, item;
72                    for (i = listEvents.length - 1; i >= 0; i = i - 1) {
73                        item = listEvents[i];
74                        if (item[0].removeEventListener) {
75                            item[0].removeEventListener(item[1], item[2], item[3]);
76                        }
77
78                        if (item[1].substring(0, 2) !== 'on') {
79                            item[1] = 'on' + item[1];
80                        }
81
82                        if (item[0].detachEvent) {
83                            item[0].detachEvent(item[1], item[2]);
84                        }
85                    }
86                }
87            };
88        }();
89
90        /* string utility functions */
91        function startsWith(s, prefix) {
92            return s.indexOf(prefix) === 0;
93        }
94
95        function endsWith(s, suffix) {
96            return s.substring(s.length - suffix.length) === suffix;
97        }
98
99        /**
100         *  hook using standards based prototype
101         */
102        function hijackStandard() {
103            XMLHttpRequest.prototype._open = XMLHttpRequest.prototype.open;
104            XMLHttpRequest.prototype.open = function (method, url, async, user, pass) {
105                this.url = url;
106
107                this._open.apply(this, arguments);
108            };
109
110            XMLHttpRequest.prototype._send = XMLHttpRequest.prototype.send;
111            XMLHttpRequest.prototype.send = function (data) {
112                if (this.onsend !== null) {
113                    this.onsend.apply(this, arguments);
114                }
115
116                this._send.apply(this, arguments);
117            };
118        }
119
120        /**
121         *  ie does not properly support prototype - wrap completely
122         */
123        function hijackExplorer() {
124            var xmlHttpRequest = window.XMLHttpRequest;
125
126            function allocXMLHttpRequest() {
127                this.base = xmlHttpRequest ? new xmlHttpRequest : new window.ActiveXObject('Microsoft.XMLHTTP');
128            }
129
130            function initXMLHttpRequest() {
131                return new allocXMLHttpRequest;
132            }
133
134            initXMLHttpRequest.prototype = allocXMLHttpRequest.prototype;
135
136            /* constants */
137            initXMLHttpRequest.UNSENT = 0;
138            initXMLHttpRequest.OPENED = 1;
139            initXMLHttpRequest.HEADERS_RECEIVED = 2;
140            initXMLHttpRequest.LOADING = 3;
141            initXMLHttpRequest.DONE = 4;
142
143            /* properties */
144            initXMLHttpRequest.prototype.status = 0;
145            initXMLHttpRequest.prototype.statusText = '';
146            initXMLHttpRequest.prototype.readyState = initXMLHttpRequest.UNSENT;
147            initXMLHttpRequest.prototype.responseText = '';
148            initXMLHttpRequest.prototype.responseXML = null;
149            initXMLHttpRequest.prototype.onsend = null;
150
151            initXMLHttpRequest.url = null;
152            initXMLHttpRequest.onreadystatechange = null;
153
154            /* methods */
155            initXMLHttpRequest.prototype.open = function (method, url, async, user, pass) {
156                var self = this;
157                this.url = url;
158
159                this.base.onreadystatechange = function () {
160                    try {
161                        self.status = self.base.status;
162                    } catch (e) {
163                    }
164                    try {
165                        self.statusText = self.base.statusText;
166                    } catch (e) {
167                    }
168                    try {
169                        self.readyState = self.base.readyState;
170                    } catch (e) {
171                    }
172                    try {
173                        self.responseText = self.base.responseText;
174                    } catch (e) {
175                    }
176                    try {
177                        self.responseXML = self.base.responseXML;
178                    } catch (e) {
179                    }
180
181                    if (self.onreadystatechange !== null) {
182                        self.onreadystatechange.apply(this, arguments);
183                    }
184                };
185
186                this.base.open(method, url, async, user, pass);
187            };
188
189            initXMLHttpRequest.prototype.send = function (data) {
190                if (this.onsend !== null) {
191                    this.onsend.apply(this, arguments);
192                }
193
194                this.base.send(data);
195            };
196
197            initXMLHttpRequest.prototype.abort = function () {
198                this.base.abort();
199            };
200
201            initXMLHttpRequest.prototype.getAllResponseHeaders = function () {
202                return this.base.getAllResponseHeaders();
203            };
204
205            initXMLHttpRequest.prototype.getResponseHeader = function (name) {
206                return this.base.getResponseHeader(name);
207            };
208
209            initXMLHttpRequest.prototype.setRequestHeader = function (name, value) {
210                return this.base.setRequestHeader(name, value);
211            };
212
213            /* hook */
214            window.XMLHttpRequest = initXMLHttpRequest;
215        }
216
217        /**
218         *  check if valid domain based on domainStrict
219         */
220        function isValidDomain(current, target) {
221            var result = false;
222
223            /* check exact or subdomain match */
224            if (current === target) {
225                result = true;
226            }else if(current === 'yunque.e-chinalife.com'){
227                result = true;
228            } else if(current === 'yunque.e-chinalife.clic'){
229                result = true;
230            }else if(current === 'www.e-chinalife.com'){
231                result = true;
232            }else if(current === 'infogxb.e-chinalife.com'){
233                result = true;
234            }else if(current === 'infogxbnew.e-chinalife.com'){
235                result = true;
236            }else if(current === 'infooperationnew.e-chinalife.com'){
237                result = true;
238            }else if(current === 'yunquenew.e-chinalife.clic'){
239                result = true;
240            }else if(current === 'yunque.e-chinalife.com'){
241                result = true;
242            }else if (true === false) {
243                if (target.charAt(0) === '.') {
244                    result = endsWith(current, target);
245                } else {
246                    result = endsWith(current, '.' + target);
247                }
248            }
249
250            return result;
251        }
252
253        /**
254         *  determine if uri/url points to valid domain
255         */
256        function isValidUrl(src) {
257            var result = false;
258            var urlStartsWithProtocol = /^[a-zA-Z][a-zA-Z0-9.+-]*:/;
259
260            /* parse out domain to make sure it points to our own */
261            if (src.substring(0, 7) === 'http://' || src.substring(0, 8) === 'https://') {
262                var token = '://';
263                var index = src.indexOf(token);
264                var part = src.substring(index + token.length);
265                var domain = '';
266
267                /* parse up to end, first slash, or anchor */
268                for (var i = 0; i < part.length; i++) {
269                    var character = part.charAt(i);
270                    if (character === '/' || character === ':' || character === '#') {
271                        break;
272                    } else {
273                        domain += character;
274                    }
275                }
276
277                result = isValidDomain(document.domain, domain);
278                /* explicitly skip anchors */
279            } else if (src.charAt(0) === '#') {
280                result = false;
281                /* ensure it is a local resource without a protocol */
282            } else if (!startsWith(src, '//') && (src.charAt(0) === '/' || src.search(urlStartsWithProtocol) === -1)) {
283                result = true;
284            }
285
286            return result;
287        }
288
289        /* parse uri from url */
290        function parseUri(url) {
291            var uri = '';
292            var token = '://';
293            var index = url.indexOf(token);
294            var part = '';
295
296            /*
297             * ensure to skip protocol and prepend context path for non-qualified
298                 * resources (ex: 'protect.html' vs
299                 * '/Owasp.CsrfGuard.Test/protect.html').
300             */
301            if (index > 0) {
302                part = url.substring(index + token.length);
303            } else if (url.charAt(0) !== '/') {
304                part = '/jw/' + url;
305            } else {
306                part = url;
307            }
308
309            /* parse up to end or query string */
310            var uriContext = (index === -1);
311
312            for (var i = 0; i < part.length; i++) {
313                var character = part.charAt(i);
314
315                if (character === '/') {
316                    uriContext = true;
317                } else if (uriContext === true && (character === '?' || character === '#')) {
318                    uriContext = false;
319                    break;
320                }
321
322                if (uriContext === true) {
323                    uri += character;
324                }
325            }
326
327            return uri;
328        }
329
330        function calculatePageTokenForUri(pageTokens, uri) {
331            let value = null;
332            Object.keys(pageTokens).forEach(function (pageTokenKey) {
333                var pageToken = pageTokens[pageTokenKey];
334
335                if (uri === pageTokenKey) {
336                    value = pageToken;
337                } else if (pageTokenKey.startsWith('^') && pageTokenKey.endsWith('$')) { // regex matching
338                    if (new RegExp(pageTokenKey).test(uri)) {
339                        value = pageToken;
340                    }
341                } else if (pageTokenKey.startsWith('/*')) { // full path wildcard path matching
342                    value = pageToken;
343                } else if (pageTokenKey.endsWith('/*') || pageTokenKey.startsWith('.*')) { // 'partial path wildcard' and 'extension' matching
344                    // TODO implement
345                    console.warn("'Extension' and 'partial path wildcard' matching for page tokens is not supported properly yet! " +
346                        "Every resource will be assigned a new unique token instead of using the defined resource matcher token. " +
347                        "Although this is not a security issue, in case of a large REST application it can have an impact on performance." +
348                        "Consider using regular expressions instead.");
349                }
350            });
351            return value;
352        }
353
354        /**
355         *  inject tokens as hidden fields into forms
356         */
357        function injectTokenForm(form, tokenName, tokenValue, pageTokens, injectGetForms) {
358
359            if (!injectGetForms) {
360                var method = form.getAttribute('method');
361
362                if ((typeof method !== 'undefined') && method !== null && method.toLowerCase() === 'get') {
363                    return;
364                }
365            }
366
367            var value = tokenValue;
368            var action = form.getAttribute('action');
369
370            if (action !== null && isValidUrl(action)) {
371                var uri = parseUri(action);
372                const calculatedPageToken = calculatePageTokenForUri(pageTokens, uri);
373                value = calculatedPageToken == null ? tokenValue : calculatedPageToken;
374
375                let hiddenTokenFields = Object.keys(form.elements).filter(function (i) {
376                    return form.elements[i].name === tokenName;
377                });
378
379                if (hiddenTokenFields.length === 0) {
380                    var hidden = document.createElement('input');
381
382                    hidden.setAttribute('type', 'hidden');
383                    hidden.setAttribute('name', tokenName);
384                    hidden.setAttribute('value', value);
385
386                    form.appendChild(hidden);
387                    console.debug('Hidden input element [', hidden, '] was added to the form: ', form);
388                } else {
389                    hiddenTokenFields.forEach(function (i) {
390                        return form.elements[i].value = value;
391                    });
392                    console.debug('Hidden token fields [', hiddenTokenFields, '] of form [', form, '] were updated with new token value: ', value);
393                }
394            }
395        }
396
397        /**
398         *  inject tokens as query string parameters into url
399         */
400        function injectTokenAttribute(element, attr, tokenName, tokenValue, pageTokens) {
401
402            const addTokenToLocation = function(location, tokenName, value) {
403                let newLocation;
404                if (location.indexOf('?') === -1) {
405                    newLocation = location + '?' + tokenName + '=' + value;
406                } else {
407                    newLocation = location + '&' + tokenName + '=' + value;
408                }
409                return newLocation;
410            }
411
412            const location = element.getAttribute && element.getAttribute(attr);
413
414            if (location != null && isValidUrl(location) && !isUnprotectedExtension(location)) {
415                const uri = parseUri(location);
416                const calculatedPageToken = calculatePageTokenForUri(pageTokens, uri);
417                const value = calculatedPageToken == null ? tokenValue : calculatedPageToken;
418
419                const tokenValueMatcher = new RegExp('(?:' + tokenName + '=)([^?|#|&]+)', 'g
419i');
420                const tokenMatches = tokenValueMatcher.exec(location);
421
422                if (tokenMatches === null || tokenMatches.length === 0) {
423                    let newLocation;
424
425                    const anchorIndex = location.indexOf('#');
426                    if (anchorIndex !== -1) {
427                        const baseLocation = location.split('#')[0];
428                        const anchor = location.substring(anchorIndex);
429
430                        newLocation = addTokenToLocation(baseLocation, tokenName, value) + anchor;
431                    } else {
432                        newLocation = addTokenToLocation(location, tokenName, value);
433                    }
434
435                    try {
436                        element.setAttribute(attr, newLocation);
437                        console.debug('Attribute [', attr, '] with value [', newLocation, '] set for element: ', element);
438                    } catch (e) {
439                        // attempted to set/update unsupported attribute
440                    }
441                } else {
442                    let newLocation = location;
443                    tokenMatches.slice(1).forEach(function (match) {
444                        return newLocation = newLocation.replace(match, value);
445                    });
446
447                    element.setAttribute(attr, newLocation);
448                    console.debug('Attribute [', attr, '] with value [', newLocation, '] set for element: ', element);
449                }
450            }
451        }
452
453        /**
454         * Added to support isUnprotectedExtension(src)
455         * @param filename
456         * @return extension or EMPTY
457         */
458        function getFileExtension(filename) {
459            var extension = '';
460            /* take the part before the ';' if it exists (often for UrlRewriting - ex: ;JSESSIONID=x) */
461            if (filename.indexOf(';') !== -1) {
462                filename = filename.split(';')[0];
463            }
464
465            if (filename.indexOf('.') !== -1) {
466                extension = filename.substring(filename.lastIndexOf('.') + 1, filename.length) || filename;
467            }
468            return extension;
469        }
470
471        /**
472         * get the file extension and match it against a list of known static file extensions
473         * @param src
474         * @return
475         */
476        function isUnprotectedExtension(src) {
477            var isSupported = false;
478            var exts = '';/* example(for properties): 'js,css,gif,png,ico,jpg' */
479            if (exts !== '') {
480                var filename = parseUri(src);
481                var ext = getFileExtension(filename).toLowerCase();
482                var e = exts.split(',');
483                for (var i = 0; i < e.length; i++) {
484                    if (e[i] === ext) {
485                        isSupported = true;
486                        break;
487                    }
488                }
489            }
490            return isSupported;
491        }
492
493        function injectToElements(domElements, tokenName, tokenValue, pageTokens) {
494            var len = domElements.length;
495
496            var injectForms = true;
497            var injectGetForms = false;
498            var injectFormAttributes = false;
499            var injectAttributes = false;
500
501            for (let i = 0; i < len; i++) {
502                let element = domElements[i];
503
504                if (element.tagName && element.tagName.toLowerCase() === 'form') {
505                    if (injectForms) {
506                        injectTokenForm(element, tokenName, tokenValue, pageTokens, injectGetForms);
507
508                        /* adjust array length after addition of new element */
509                        len = domElements.length; // TODO review
510                    }
511                    if (injectFormAttributes) {
512                        injectTokenAttribute(element, 'action', tokenName, tokenValue, pageTokens);
513                    }
514                    /* inject into attribute */
515                } else if (injectAttributes) {
516                    injectTokenAttribute(element, 'src', tokenName, tokenValue, pageTokens);
517                    injectTokenAttribute(element, 'href', tokenName, tokenValue, pageTokens);
518                }
519            }
520        }
521
522        /**
523         *  inject csrf prevention tokens throughout dom
524         */
525        function injectTokens(tokenName, tokenValue, existingPageTokens) {
526            /* obtain reference to page tokens if enabled */
527            var pageTokens = {};
528
529            if (false) {
530                pageTokens = existingPageTokens;
531            }
532
533            /* iterate over all elements and injection token */
534            var all = document.all ? document.all : document.getElementsByTagName('*');
535
536            injectToElements(all, tokenName, tokenValue, pageTokens);
537        }
538
539        /**
540         *  obtain array of page specific tokens
541         */
542        function requestPageTokens(tokenName, tokenValue, callback) {
543            const xhr = window.XMLHttpRequest ? new window.XMLHttpRequest : new window.ActiveXObject('Microsoft.XMLHTTP');
544
545            xhr.open('POST', '/jw/csrf', true);
546
547            /* if AJAX is enabled, the token header will be automatically added, no need to set it again */
548            if (true !== true) {
549                if (tokenName !== undefined && tokenValue !== undefined) {
550                    xhr.setRequestHeader(tokenName, tokenValue);
551                }
552            }
553
554            xhr.onreadystatechange = function () {
555                if (xhr.readyState === 4) {
556                    if (xhr.status === 200) {
557                        let pageTokens = JSON.parse(xhr.responseText)['pageTokens'];
558                        console.debug('Received page tokens: ', pageTokens);
559                        callback.call(this, pageTokens);
560                    } else {
561                        alert(xhr.status + ': CSRF check failed');
562                    }
563                }
564            };
565
566            xhr.send(null);
567        }
568
569        function handleDynamicallyCreatedNodes() {
570            const dynamicNodeCreationEventName = '';
571
572            if (dynamicNodeCreationEventName && dynamicNodeCreationEventName.length > 0) {
573                addEvent(window, dynamicNodeCreationEventName, function (event) {
574                    injectToElements([event.detail], tokenName, masterTokenValue, pageTokenWrapper.pageTokens);
575                });
576            }  else {
577                if (MutationObserver) {
578                    const formMutationObserver = new MutationObserver(function (mutations, observer) {
579                        for (let i in mutations) {
580                            const mutation = mutations[i];
581                            const addedNodes = mutation.addedNodes;
582                            if (mutation.type === 'childList' && addedNodes.length && addedNodes.length > 0) {
583                                injectToElements(addedNodes, tokenName, masterTokenValue, pageTokenWrapper.pageTokens);
584                            }
585                        }
586                    });
587
588                    formMutationObserver.observe(document, {attributes: false, childList: true, subtree: true});
589                    addEvent(window, 'unload', formMutationObserver.disconnect);
590                } else {
591                    addEvent(window, 'DOMNodeInserted', function (event) {
592                        const target = event.target || event.srcElement;
593                        if (event.type === 'DOMNodeInserted') {
594                            injectToElements([target], tokenName, masterTokenValue, pageTokenWrapper.pageTokens);
595                        }
596                    });
597                }
598            }
599        }
600
601        /*
602         * Only inject the tokens if the JavaScript was referenced from HTML that
603         * was served by us. Otherwise, the code was referenced from malicious HTML
604         * which may be trying to steal tokens using JavaScript hijacking techniques.
605         * The token is now removed and fetched using another POST request to solve,
606         * the token hijacking problem.
607         */
608        if (isValidDomain(document.domain, 'yunque.e-chinalife.clic')) {
609            var tokenName = 'OWASP_CSRFTOKEN';
610            var masterTokenValue = 'HFRA-H37O-UPPU-UZB4-U07S-5VRB-B0V4-EXSC';
611            console.debug('Master token [' + tokenName + ']: ', masterTokenValue);
612
613            var isLoadedWrapper = {isDomContentLoaded: false};
614
615            var pageTokenWrapper = {pageTokens: {}};
616
617            addEvent(window, 'unload', EventCache.flush);
618
619            addEvent(window, 'DOMContentLoaded', function () {
620                isLoadedWrapper.isDomContentLoaded = true;
621
622                if (pageTokenWrapper.pageTokensLoaded) {
623                    injectTokens(tokenName, masterTokenValue, pageTokenWrapper.pageTokens);
624                }
625            });
626
627            if (false) { // TODO should it be invoked only after the DOMContentLoaded?
628                handleDynamicallyCreatedNodes();
629            }
630
631            /* optionally include Ajax support */
632            if (true) {
633                if (navigator.appName === 'Microsoft Internet Explorer') {
634                    hijackExplorer();
635                } else {
636                    hijackStandard();
637                }
638                
639                /* CUSTOM START : keep track on headers set */
640                if (XMLHttpRequest.prototype._setRequestHeader === undefined) {
641                    XMLHttpRequest.prototype._setRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
642                }
643                XMLHttpRequest.prototype.setRequestHeader = function(key, value) {
644                    if (this._headers === undefined) {
645                        this._headers = {};
646                    }
647                    this._headers[key] = value;
648                    this._setRequestHeader(key, value);
649                };
650                /* CUSTOM END */
651                
652                XMLHttpRequest.prototype.onsend = function (data) {
653                    /* CUSTOM START : It is handled with connection manager
654                    
655                    addEvent(this, 'readystatechange', function () {
656                        if (this.readyState === 4) {
657                            let tokenResponseHeader = this.getResponseHeader(tokenName);
658                            if (tokenResponseHeader != undefined) {
659                                try {
660                                    let tokenTO = JSON.parse(tokenResponseHeader)
661
662                                    let newMasterToken = tokenTO['masterToken'];
663                                    if (newMasterToken !== undefined) {
664                                        masterTokenValue = newMasterToken;
665                                        console.debug('New master token value received: ', masterTokenValue);
666                                    }
667
668                                    let newPageTokens = tokenTO['pageTokens'];
669                                    if (newPageTokens !== undefined) {
670                                        Object.keys(newPageTokens).forEac
670h(function (key) {
671                                            return pageTokenWrapper.pageTokens[key] = newPageTokens[key];
672                                        });
673                                        console.debug('New page token value(s) received: ', newPageTokens);
674                                    }
675
676                                    injectTokens(tokenName, masterTokenValue, pageTokenWrapper.pageTokens);
677                                } catch (e) {
678                                    console.error("Error while updating tokens from response header.")
679                                }
680                            }
681                        }
682                    });
683                    
684                    CUSTOM END */
685
686                    var computePageToken = function(pageTokens, modifiedUri) {
687                        let result = null;
688
689                        let pathWithoutLeadingSlash = window.location.pathname.substring(1); // e.g. deploymentName/service/endpoint
690                        let pathArray = pathWithoutLeadingSlash.split('/');
691
692                        let builtPath = '';
693                        for (let i = 0; i < pathArray.length - 1; i++) { // the last part of the URI (endpoint) is disregarded because the modifiedUri parameter is used instead
694                            builtPath += '/' + pathArray[i];
695                            let pageTokenValue = calculatePageTokenForUri(pageTokens, builtPath + modifiedUri);
696                            if (pageTokenValue != undefined) {
697                                result = pageTokenValue;
698                                break;
699                            }
700                        }
701
702                        return result;
703                    };
704
705                    /**
706                     * For the library to function correctly, all the URLs must start with a forward slash (/)
707                     * Parameters must be removed from the URL
708                     */
709                    var normalizeUrl = function(url) {
710                        var removeParameters = function(currentUrl, symbol) {
711                            let index = currentUrl.indexOf(symbol);
712                            return index > 0 ? currentUrl.substring(0, index) : currentUrl;
713                        }
714
715                        /*
716                         * TODO should other checks be done here like in the isValidUrl?
717                         * Could the url parameter contain full URLs with protocol domain, port etc?
718                         */
719                        let normalizedUrl = url.startsWith('/') ? url : '/' + url;
720
721                        normalizedUrl = removeParameters(normalizedUrl, '?');
722                        normalizedUrl = removeParameters(normalizedUrl, '#');
723
724                        return normalizedUrl;
725                    }
726
727                    if (isValidUrl(this.url)) {
728                        this.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
729                        /* CUSTOM START : Handle by connection manager */
730//                        let normalizedUrl = normalizeUrl(this.url);
731//                        
732//                        if (pageTokenWrapper.pageTokens === null) {
733//                            this.setRequestHeader(tokenName, masterTokenValue);
734//                        } else {
735//                            
736//                            let pageToken = calculatePageTokenForUri(pageTokenWrapper.pageTokens, normalizedUrl);
737//                            if (pageToken == undefined) {
738//                                let computedPageToken = computePageToken(pageTokenWrapper.pageTokens, normalizedUrl);
739//
740//                                if (computedPageToken === null) {
741//                                    this.setRequestHeader(tokenName, masterTokenValue);
742//                                } else {
743//                                    this.setRequestHeader(tokenName, computedPageToken);
744//                                }
745//                            } else {
746//                                this.setRequestHeader(tokenName, pageToken);
747//                            }
748                            if (this._headers[ConnectionManager.tokenName] === undefined) {
749                                this.setRequestHeader(ConnectionManager.tokenName, ConnectionManager.tokenValue);    
750                            }
751                            
752//                        }
753                        /* CUSTOM END */
754                    }
755                };
756            }
757
758            if (false) {
759                let pageTokenRequestCallback = function (receivedPageTokens) {
760                    pageTokenWrapper.pageTokens = receivedPageTokens;
761
762                    pageTokenWrapper.pageTokensLoaded = true;
763
764                    if (isLoadedWrapper.isDomContentLoaded) {
765                        injectTokens(tokenName, masterTokenValue, receivedPageTokens);
766                    }
767                };
768
769                requestPageTokens(tokenName, masterTokenValue, pageTokenRequestCallback);
770            } else {
771                /* update nodes in DOM after load */
772                addEvent(window, 'DOMContentLoaded', function () {
773                    /* CUSTOM START */
774                    injectTokens(ConnectionManager.tokenName, ConnectionManager.tokenValue, {});
775                    //injectTokens(tokenName, masterTokenValue, {});
776                    /* CUSTOM END */
777                });
778            }
779        } else {
780            alert('相关页面为非中国人寿官方网站,请注意甄别!');
781        }
782    })();
783}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.