PageSourceSearch

https://www.marktbreit.de/page-view-counter/page-view-counter-ajax.js

js marktbreit.de collected 2026-10-02 17:58:29 UTC 5,538 bytes, 196 lines download raw bytes

1(function () {
2  'use strict';
3
4  var script = document.currentScript || (function () {
5    var scripts = document.getElementsByTagName('script');
6    return scripts[scripts.length - 1];
7  })();
8
9  function attr(name, fallback) {
10    if (!script) {
11      return fallback;
12    }
13    var value = script.getAttribute(name);
14    return value === null ? fallback : value;
15  }
16
17  function defaultEndpoint() {
18    if (!script || !script.src) {
19      return 'page-view-counter-track.php';
20    }
21    return script.src.replace(/page-view-counter-ajax\.js(?:\?.*)?$/, 'page-view-counter-track.php');
22  }
23
24  function collectBrowserData() {
25    var data = {};
26
27    if (typeof navigator.hardwareConcurrency !== 'undefined') {
28      data.hardwareConcurrency = navigator.hardwareConcurrency;
29    }
30    if (typeof navigator.language !== 'undefined') {
31      data.language = navigator.language;
32    }
33    if (typeof navigator.languages !== 'undefined') {
34      data.languages = Array.prototype.slice.call(navigator.languages, 0, 10);
35    }
36    if (typeof navigator.maxTouchPoints !== 'undefined') {
37      data.maxTouchPoints = navigator.maxTouchPoints;
38    }
39    if (typeof navigator.pdfViewerEnabled !== 'undefined') {
40      data.pdfViewerEnabled = navigator.pdfViewerEnabled;
41    }
42    if (typeof navigator.webdriver !== 'undefined') {
43      data.webdriver = navigator.webdriver;
44    }
45    if (typeof navigator.userAgent !== 'undefined') {
46      data.userAgent = navigator.userAgent;
47    }
48
49    return data;
50  }
51
52  function safeEndpoint(value, fallback) {
53    try {
54      var url = new URL(value, window.location.href);
55      var fallbackUrl = new URL(fallback, window.location.href);
56
57      // Keine externen Endpunkte erlauben. Sonst könnte ein manipuliertes HTML-Attribut
58      // die aktuelle URL und optionale Browserdaten an fremde Domains schicken.
59      if (url.origin !== window.location.origin) {
60        return fallbackUrl.href;
61      }
62
63      // Nur den vorgesehenen Tracking-Endpunkt akzeptieren.
64      if (!/\/page-view-counter-track\.php$/.test(url.pathname)) {
65        return fallbackUrl.href;
66      }
67
68      return url.href;
69    } catch (e) {
70      return fallback;
71    }
72  }
73
74  var fallbackEndpoint = defaultEndpoint();
75  var endpoint = safeEndpoint(attr('data-pvc-endpoint', fallbackEndpoint), fallbackEndpoint);
76  var includeBrowserFields = attr('data-pvc-browser-fields', '0') === '1';
77
78  // Debug-Ausgabe nur, wenn sie ausdrücklich aktiviert wurde.
79  // data-pvc-debug-target alleine reicht nicht mehr.
80  var jsDebugEnabled = attr('data-pvc-debug', '0') === '1';
81  var debugTargetId = jsDebugEnabled ? attr('data-pvc-debug-target', '') : '';
82  var debugTarget = debugTargetId ? document.getElementById(debugTargetId) : null;
83
84  var payload = {
85    url: window.location.href,
86    clientTs: Math.round(Date.now() / 1000)
87  };
88
89  if (includeBrowserFields) {
90    payload.browser = collectBrowserData();
91  }
92
93  var body = JSON.stringify(payload);
94
95  function showDebug(text) {
96    if (!debugTarget) {
97      return;
98    }
99    debugTarget.textContent = text;
100  }
101
102  function clearDebug() {
103    if (!debugTarget) {
104      return;
105    }
106    debugTarget.textContent = '';
107  }
108
109  function buildDebugOutput(status, statusText, text) {
110    return (
111      'HTTP-Status: ' + status + ' ' + (statusText || '') + '\n' +
112      'Endpoint: ' + endpoint + '\n' +
113      'Payload: ' + body + '\n\n' +
114      text
115    );
116  }
117
118  function sendWithFetch() {
119    if (typeof fetch !== 'function') {
120      return false;
121    }
122
123    clearDebug();
124
125    fetch(endpoint, {
126      method: 'POST',
127      headers: { 'Content-Type': 'application/json' },
128      body: body,
129      credentials: 'same-origin',
130      keepalive: true
131    }).then(function (response) {
132      if (!debugTarget) {
133        return null;
134      }
135
136      return response.text().then(function (text) {
137        // Bei PHP-debug=false kommt normalerweise 204 No Content ohne Body zurück.
138        // Dann soll im Debug-Div gar nichts stehen, auch wenn das Div im HTML vorhanden ist.
139        if (!text) {
140          clearDebug();
141          return;
142        }
143
144        showDebug(buildDebugOutput(response.status, response.statusText, text));
145      });
146    }).catch(function (error) {
147      // Netzwerkfehler nur anzeigen, wenn explizit ein Debug-Div vorhanden ist.
148      // Das passiert unabhängig vom PHP-Debug, weil bei Netzwerkfehlern keine PHP-Antwort kommt.
149      if (debugTarget) {
150        showDebug(
151          'Fehler beim Aufruf von: ' + endpoint + '\n' +
152          String(error && error.message ? error.message : error) + '\n\n' +
153          'Payload: ' + body
154        );
155      }
156    });
157
158    return true;
159  }
160
161  function sendWithXHR() {
162    var xhr = new XMLHttpRequest();
163    xhr.open('POST', endpoint, true);
164    xhr.setRequestHeader('Content-Type', 'application/json');
165
166    clearDebug();
167
168    xhr.onreadystatechange = function () {
169      if (debugTarget && xhr.readyState === 4) {
170        if (!xhr.responseText) {
171          clearDebug();
172          return;
173        }
174
175        showDebug(buildDebugOutput(xhr.status, xhr.statusText, xhr.responseText));
176      }
177    };
178    xhr.onerror = function () {
179      if (debugTarget) {
180        showDebug('Fehler beim XMLHttpRequest-Aufruf von: ' + endpoint + '\nPayload: ' + body);
181      }
182    };
183    xhr.send(body);
184  }
185
186  if (!debugTarget && navigator.sendBeacon) {
187    var blob = new Blob([body], { type: 'application/json' });
188    if (navigator.sendBeacon(endpoint, blob)) {
189      return;
190    }
191  }
192
193  if (!sendWithFetch()) {
194    sendWithXHR();
195  }
196})();

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.