Userrestriktionen der Fritz-Oberfläche bei Nutzung eines veralteten Browsers

Das Problem mit dem Feedback-Formular ist bereits seit einiger Zeit behoben.
 
Schön, ich hatte zuletzt nichts mehr zu melden.
 
Ich hab jetzt mal einen permanenten Scanner geschrieben der die Abhängigkeiten der JavaScript methoden des Browser-Checks im Detail aufzeigt.


Also diese Scripts alle anzupassen auch mit älteren Browsern zu funktionieren wird wohl nicht passieren.
Aber man sieht auch dass alle Methoden bereits vor der Browser-Check Barriere genutzt wurden.

Wenn ich da eines Tages rekursive Dependencies anzeige wird es eine Menge Seiten im Webinterface betreffen...
Man kann es ahnen wenn man die einzelnen Files in der Usage Spalte verfolgt und deren Dependencies anschaut.

Um den Test zu umgehen hab ich die simpelste Lösung auch ohne Adblocker gefunden, ein Bookmark genügt:

Starting with firmware 6.36 you can defeat the Browser-Check by calling https://fritz.box/?nbc=1. (nbc = no browser check)
This will set the gNbc variable (global no browser check, see below) and no further checks occur for this session.
 
Zuletzt bearbeitet:
Selbst mit Chrome aktuell, wird mir auf dem Mac die Ansicht der FB verweigert.
Da musst du wohl echt nochmal auf díe Suche gehen. Meine (aktuellen) Chromes funktionieren auf Windows 10, Linux Manjaro, Android 9 und iPhone 11 (aktuelles iOS).
 
Ich hab jetzt mal einen permanenten Scanner geschrieben der die Abhängigkeiten der JavaScript methoden des Browser-Checks im Detail aufzeigt.
Eine kleine Anmerkung dazu: Es ist nicht Promise.resolve welches akut problematisch ist (das kann Firefox nämlich schon seit Version 29), sondern Promise.finally, welches in Firefox erst seit Version 58 unterstützt wird.

Neben der einfachen Umgehung der Browserprüfung (sei es durch blockieren der browser.js, oder per nbc-Parameter in der URL) gibt es in diesem Fall noch eine weitere Lösungsmöglichkeit, die (abgesehen vom Wechsel auf einen Browser, der Promise.finally nativ unterstützt) eigentlich die sauberste ist: Die fehlende Funktionalität lässt sich in diesem Fall nämlich glücklicherweise auch per Polyfill nachrüsten (hab mir eins von polyfill.io geschnappt), welches man dann z.B. per Userscript auf der Benutzeroberfläche der Fritzbox nachladen kann (theoretisch könnte AVM das gleiche auch von Haus aus tun, aber egal…):
Code:
// ==UserScript==
// @name        Fritz!Box Polyfill
// @namespace   http://www.buttercookie.de
// @include     /https?:\/\/(.+\.)?(my)?fritz\.(box|nas)\//
// @version     1
// @run-at      document-start
// @grant       none
// ==/UserScript==

// Promise.prototype.finally polyfill (polyfill.io)
const promiseFinallyPolyfill = "(function(self, undefined) {function CreateMethodProperty(e,r,t){var a={value:t,writable:!0,enumerable:!1,configurable:!0};Object.defineProperty(e,r,a)}function Get(n,t){return n[t]}function IsCallablen{return'function'==typeof n}function ToObject(e){if(null===e||e===undefined)throw TypeError();return Object(e)}function GetV(t,e){return ToObject(t)[e]}function GetMethod(e,n){var r=GetV(e,n);if(null===r||r===undefined)return undefined;if(!1===IsCallabler)throw new TypeError('Method not callable: '+n);return r}function Type(e){switch(typeof e){case'undefined':return'undefined';case'boolean':return'boolean';case'number':return'number';case'string':return'string';case'symbol':return'symbol';default:return null===e?'null':'Symbol'in self&&(e instanceof self.Symbol||e.constructor===self.Symbol)?'symbol':'object'}}function IsConstructor(t){return'object'===Type(t)&&('function'==typeof t&&!!t.prototype)}function SpeciesConstructor(e,o){var r=Get(e,'constructor');if(r===undefined)return o;if('object'!==Typer)throw new TypeError('O.constructor is not an Object');var n='function'==typeof self.Symbol&&'symbol'==typeof self.Symbol.species?r[self.Symbol.species]:undefined;if(n===undefined||null===n)return o;if(IsConstructor(n))return n;throw new TypeError('No constructor found')}!function(){var t=Function.prototype.bind.call(Function.prototype.call,Promise.prototype.then),o=function(t,o){return new t(function(t){t(o())})};CreateMethodProperty(Promise.prototype,'finally',function(e){var r=this;if('object'!==Typer)throw new TypeError('Method %PromisePrototype%.finally called on incompatible receiver '+Object.prototype.toString.call(r));var n=SpeciesConstructor(r,Promise);if(!1===IsCallable(e))var i=e,c=e;else i=function(r){return t(o(n,e),function(){return r})},c=function(r){return t(o(n,e),function(){throw r})};return t(r,i,c)})}();})('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});";

const scriptElement = document.createElement('script');
scriptElement.textContent = promiseFinallyPolyfill;
const parentElement = document.head || document.documentElement;
parentElement.insertBefore(scriptElement, parentElement.firstChild);
Nach Installation per Greasemonkey o.ä. wird der Browsercheck anstandslos passiert. (Wenn man auf die Fritzbox direkt über die IP-Adresse oder über Myfritz oder anderweitig von außen zugreift, also nicht über die interne fritz.box/fritz.nas/myfritz.box-Domain, muss man das Skript noch für die jeweiligen Domains freischalten, damit es dort ebenfalls geladen wird.)
 
Eine kleine Anmerkung dazu: Es ist nicht Promise.resolve welches akut problematisch ist (das kann Firefox nämlich schon seit Version 29), sondern Promise.finally, welches in Firefox erst seit Version 58 unterstützt wird.

Guter Hinwes, danke, dann trenne ich die beiden auf und scanne die auch separat.
Die werden zwar zeitgleich getestet, trotzdem ist die Referenz intteressant was wo genutzt wird.

Zur Polyfill Methide werde ich vorerst dein Posting verlinken.
 
Die fehlende Funktionalität lässt sich in diesem Fall nämlich glücklicherweise auch per Polyfill nachrüsten (hab mir eins von polyfill.io geschnappt), welches man dann z.B. per Userscript auf der Benutzeroberfläche der Fritzbox nachladen kann [...]

Nach Installation per Greasemonkey o.ä. wird der Browsercheck anstandslos passiert.

Hallo, sorry dass ich hiervon so wenig Ahnung hab... ich verwende Firefox 54.0.1 (weil der noch die alten Plugins unterstützt), hab das Script mit Greasemonkey 3.17 installiert, es ist auch aktiv wenn ich auf die Box gehe, aber ich werde trotzdem auf sorry.lua umgeleitet.

Muss ich evtl. noch was anderes machen außer das Script zu installieren / kann mir einer das mit 'von polyfill.io nachrüsten' Schritt-für-Schritt erklären? Oder ist meine Greasemonkey-Version evtl. zu alt?

Was GENAU geht im FritzBox-Menü eigentlich nicht, wenn diese Funktion fehlt? (wenn ich einfach nur browser.js blocke)
 
Umm... wenn ich mit meinem etwas älteren Browser (hier: Firefox 54.0.1, bei dem ich über GreaseMonkey die Funktion Promise.prototype.finally ergänzt habe) im FritzBox-Menü auf 'Assistenten' gehe, wird die Seite nicht geladen (es wird ewig der sich drehende 'Ladekringel' gezeigt)...

Könnte einer mit Ahnung sich das evtl. mal ansehen und mir sagen, was / welche Funktion ich da noch ergänzen muss, damit auch das unter meinem alten Browser zugänglich bleibt? In Waterfox z.B. läuft es.
 
Hat es einen bestimmten Grund, dass du genau auf Firefox 54 hängen geblieben bist? Wenn es nur um die alten Add-ons geht, stellt sich das Problem ja eigentlich erst ab Firefox 57, d.h. alle Versionen bis einschließlich 56 sollten im Allgemeinen kein Problem sein.
Die für die Assistenten geladene wizardhome.js benötigt nämlich die Javascript-Funktionalität "Spread in object literals", die erst mit Firefox 55 eingeführt wurde, sodass ein minimales Update um eine Version das Problem eigentlich lösen sollte.

Falls das aus welchen Gründen auch immer keine Alternative ist (oder man z.B. stattdessen die 52 ESR nutzt), hier eine erweiterte Fassung meines Greasemonkey-Scriptes:
Javascript:
// ==UserScript==
// @name        Fritz!Box Polyfill
// @namespace   http://www.buttercookie.de
// @include     /https?:\/\/(.+\.)?(my)?fritz\.(box|nas)\//
// @version     2
// @run-at      document-start
// @grant       GM_xmlhttpRequest
// ==/UserScript==

const polyfills = [/* Promise.prototype.finally polyfill (from polyfill.io)*/ "(function(self, undefined) {function CreateMethodProperty(e,r,t){var a={value:t,writable:!0,enumerable:!1,configurable:!0};Object.defineProperty(e,r,a)}function Get(n,t){return n[t]}function IsCallable(n){return'function'==typeof n}function ToObject(e){if(null===e||e===undefined)throw TypeError();return Object(e)}function GetV(t,e){return ToObject(t)[e]}function GetMethod(e,n){var r=GetV(e,n);if(null===r||r===undefined)return undefined;if(!1===IsCallable(r))throw new TypeError('Method not callable: '+n);return r}function Type(e){switch(typeof e){case'undefined':return'undefined';case'boolean':return'boolean';case'number':return'number';case'string':return'string';case'symbol':return'symbol';default:return null===e?'null':'Symbol'in self&&(e instanceof self.Symbol||e.constructor===self.Symbol)?'symbol':'object'}}function IsConstructor(t){return'object'===Type(t)&&('function'==typeof t&&!!t.prototype)}function SpeciesConstructor(e,o){var r=Get(e,'constructor');if(r===undefined)return o;if('object'!==Type(r))throw new TypeError('O.constructor is not an Object');var n='function'==typeof self.Symbol&&'symbol'==typeof self.Symbol.species?r[self.Symbol.species]:undefined;if(n===undefined||null===n)return o;if(IsConstructor(n))return n;throw new TypeError('No constructor found')}!function(){var t=Function.prototype.bind.call(Function.prototype.call,Promise.prototype.then),o=function(t,o){return new t(function(t){t(o())})};CreateMethodProperty(Promise.prototype,'finally',function(e){var r=this;if('object'!==Type(r))throw new TypeError('Method %PromisePrototype%.finally called on incompatible receiver '+Object.prototype.toString.call(r));var n=SpeciesConstructor(r,Promise);if(!1===IsCallable(e))var i=e,c=e;else i=function(r){return t(o(n,e),function(){return r})},c=function(r){return t(o(n,e),function(){throw r})};return t(r,i,c)})}();})('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});",
                   /* Spread syntax for object literals helper (from babeljs.io) */ "function ownKeys(object,enumerableOnly){var keys=Object.keys(object);if(Object.getOwnPropertySymbols){var symbols=Object.getOwnPropertySymbols(object);if(enumerableOnly) symbols=symbols.filter(function(sym){return Object.getOwnPropertyDescriptor(object,sym).enumerable});keys.push.apply(keys,symbols)} return keys} function _objectSpread(target){for(var i=1;i<arguments.length;i++){var source=arguments[i]!=null?arguments[i]:{};if(i%2){ownKeys(Object(source),!0).forEach(function(key){_defineProperty(target,key,source[key])})}else if(Object.getOwnPropertyDescriptors){Object.defineProperties(target,Object.getOwnPropertyDescriptors(source))}else{ownKeys(Object(source)).forEach(function(key){Object.defineProperty(target,key,Object.getOwnPropertyDescriptor(source,key))})}} return target} function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0})}else{obj[key]=value} return obj}",
                  ]

for (polyfill of polyfills) {
  const scriptElement = document.createElement('script');
  scriptElement.textContent = polyfill;
  const parentElement = document.head || document.documentElement;
  parentElement.insertBefore(scriptElement, parentElement.firstChild);
}

window.addEventListener('beforescriptexecute',
  event => {
    let originalScript = event.target;

    if(/\/wizardhome\.js(\?.*)?$/.test(originalScript.src)) 
    {
      replaceScript(event, fixupWizardHome);
    }
  }
);

function fixupWizardHome(aInput) {
  return aInput.replace('{...params}', '_objectSpread({}, params)');
}

function replaceScript(aBeforeScriptEvt, aFixupScriptCallback) {
  aBeforeScriptEvt.preventDefault();
  aBeforeScriptEvt.stopPropagation();
  let originalScript = aBeforeScriptEvt.target;

  GM_xmlhttpRequest({
    method: "GET",
    url: originalScript.src,
    onload: res => {
      let text = res.responseText;
      text = aFixupScriptCallback(text);

      let replacementScript = document.createElement('script');
      replacementScript.textContent = text;
      if (originalScript.hasAttribute('id')) {
        replacementScript.id = originalScript.id;
      }
      originalScript.parentNode.replaceChild(replacementScript, originalScript);
    }
  });
}
Aus mir noch unbekannten Gründen hängt der erste Aufruf der Assistenten-Seite aber immer noch, obwohl in der Browserkonsole keine Fehlermeldungen mehr auftauchen. Ab dem zweiten Versuch funktioniert es dann aber (wobei ich jetzt nicht alle Assistenten im Einzelnen durchprobiert habe), sodass das fürs Erste trotzdem mal ausreichen muss.
 
  • Like
Reaktionen: guru1d
Hat es einen bestimmten Grund, dass du genau auf Firefox 54 hängen geblieben bist?
Ja... ich habe unten im Fenster (Status-Leiste) mehrere Programme, wie Ghostery, NoScript usw., alle als schöne kleine Symbole, und auch einen Ladebalken usw. Bei allen späteren Firefox-Versionen scheint das nicht mehr so zu gehen, da sind dann nur noch mittelgroße Smbole + Text, was mir eben gar nicht gefällt... eben mit Firefox 55.0.1 getestet.

Klar könnte ich Waterfox nehmen, hab ich auch parallel installiert, aber es geht mir mehr um's 'Prinzip'.

Und ja, natürlich auch wg. der alten Add-Ons, INSBESONDERE wegen 'Classic Theme Restorer'. Ja, nennt mich altmodisch. Trotzdem.

Falls das aus welchen Gründen auch immer keine Alternative ist (oder man z.B. stattdessen die 52 ESR nutzt), hier eine erweiterte Fassung meines Greasemonkey-Scriptes:
Dieses Script funktioniert bei mir (in GreaseMonkey 3.17) nicht, genau so wenig wie Dein Script weiter oben zu 'Finally'... ich musste stattdessen den Code von
https://github.com/matthew-andrews/Promise.prototype.finally/blob/master/finally.js verwenden, damit 'Finally' bei mir ging.

Vielleicht könntest Du etwas näher erklären, was Dein 'Spread' Script genau macht, bzw. was zu machen ist, damit FritzBox Assistenten angezeigt werden?
 
Hmm, warum das jetzt bei mir funktioniert (ebenfalls mit Greasemonkey 3.17) und bei dir nicht, weiß ich auch nicht. Ob 52.9 (ESR) vs. 54 da den Unterschied ausmacht??? …möchte die alte Installation aber auch nicht für Versuche durcheinanderbringen (Downthemall habe ich auch erst so richtig entdeckt, nachdem die 57 eigentlich schon draußen war, und die Webextension-API hat ja selbst heute noch, Jahre später, dämliche Einschränkungen bezüglich Downloadmanagern…).

Wenn du versuchen willst, das selber irgendwie zum laufen zu bringen – da es sich bei "Spread in object literals" um eine komplett neue Javascript-Syntax handelt, kann man da nicht einfach die fehlenden Funktionen nachladen, sondern muss das von der Fritzbox kommende Skript an sich in irgendeiner Form direkt umschreiben. Den dazu nötigen Inhalt habe ich mir von https://babeljs.io/repl abgeschaut – wenn ich dort den Inhalt der reinkopiere, und dann bei "targets" statt der Standardvorgabe "firefox 52" eintrage, sehe ich, wie der Code umgeschrieben werden muss, damit er auch in den älteren Firefox-Versionen läuft.

Den von babeljs ergänzten Codeblock mit den drei zusätzlichen Hilfsfunktionen, die die neue "Spread"-Syntax händisch nachbilden, habe ich mir rauskopiert und lade ihn oben (im Teil mit dem for (polyfill of polyfills)-Block) in die Seite, genau so wie das Promise.prototype.finally-Polyfill (welches bei dir warum auch immer nicht funktioniert).

Im Anchluss muss ich dann noch das von der Fritzbox kommende Skript so umschreiben, dass es nicht diese neue, bis einschließlich Firefox 54 nicht unterstützte Spread-Syntax mit den drei Punkten nutzt, sondern stattdessen meine äquivalenten Hilfsfunktionen aufruft. Über den beforescriptexecute-Eventhandler kann ich jedes Skript, welches die Fritzbox-Homepage zu laden versucht, abfangen. Sobald die wizardhome.js erkannt wird, tritt mein Code in Aktion: Mit preventDefault()/stopPropagation() blockiere ich die Ausführung des Originalskriptes. Per GM_xmlhttpRequest hole ich mir dann den Inhalt des Skriptes, und biege per einfachem Suchen-und-Ersetzen (aInput.replace('{...params}', '_objectSpread({}, params)') die vom alten Firefox nicht unterstützte Spread-Syntax ({...params}) auf meine oben geladene Hilfsfunktion (objectSpread()) um.

Den so modifizierten Code der wizardhome.js schreibe ich dann in ein neues Skript-Tag, welches ich schließlich an Stelle des originalen wizardhome.js-Skriptes in die Seite lade. Wichtig ist, dabei auch die id des originalen Skript-Tags zu übernehmen, damit der Fritzbox-Code das Skript beim Verlassen der Assistenten wieder entfernen kann.
 
Hmm, warum das jetzt bei mir funktioniert (ebenfalls mit Greasemonkey 3.17) und bei dir nicht, weiß ich auch nicht.
Komisch, ich hab jetzt eben nochmal getestet, und es läuft (auch wie von Dir beschrieben mit dem 'Hänger' beim ersten Aufruf der Assistenten). Könnte evtl. daran liegen, dass ich beim ersten Mal das Script von hier direkt über Zwischenablage in GreaseMonkey eingefügt hab; diesmal bin ich einen Zwischenschritt über Notepad++ gegangen, wo dann auch die richtige 'Formatierung' mit Einrückungen usw. gezeigt wurde statt eine einzige lange Zeile an Code...

Danke für die ausführliche Erklärung (so gesehen echt tolle Arbeit von Dir). Sag bitte Bescheid, wenn Du das mit dem 'Hänger' noch rausfinden solltest...
 
Keine Ursache. Zum 'Hänger' hatte ich noch eine Vermutung, die sich tatsächlich bewahrheitet hat – es lag daran, das GM_xmlhttpRequest() standardmäßig asynchron funktioniert, d.h. während dem Abruf des originalen Skriptes wird die Ausführung meines Userskriptes unterbrochen, und in der Zwischenzeit kann dann irgendwelcher Fritzbox-Code laufen, der dann über das noch fehlende Assistenten-Skript stolpert. (Beim zweiten Mal funktioniert es dann vielleicht weil das Skript sofort aus dem Cache geladen wird und daher die Unterbrechung kürzer ausfällt? Weiß ich jetzt aber auch nicht sicher…).
Mit einer entsprechenden Anpassung auf synchronen Aufruf der Funktion kann dagegen nichts mehr schief gehen und das Skript wird jetzt wohl garantiert ausgetauscht bevor der restliche Fritzbox-Code etwas davon mitbekommen könnte:
Javascript:
// ==UserScript==
// @name        Fritz!Box Polyfill
// @namespace   http://www.buttercookie.de
// @include     /https?:\/\/(.+\.)?(my)?fritz\.(box|nas)\//
// @version     2.1
// @run-at      document-start
// @grant       GM_xmlhttpRequest
// ==/UserScript==

const polyfills = [/* Promise.prototype.finally polyfill (from polyfill.io) */ "(function(self, undefined) {function CreateMethodProperty(e,r,t){var a={value:t,writable:!0,enumerable:!1,configurable:!0};Object.defineProperty(e,r,a)}function Get(n,t){return n[t]}function IsCallable(n){return'function'==typeof n}function ToObject(e){if(null===e||e===undefined)throw TypeError();return Object(e)}function GetV(t,e){return ToObject(t)[e]}function GetMethod(e,n){var r=GetV(e,n);if(null===r||r===undefined)return undefined;if(!1===IsCallable(r))throw new TypeError('Method not callable: '+n);return r}function Type(e){switch(typeof e){case'undefined':return'undefined';case'boolean':return'boolean';case'number':return'number';case'string':return'string';case'symbol':return'symbol';default:return null===e?'null':'Symbol'in self&&(e instanceof self.Symbol||e.constructor===self.Symbol)?'symbol':'object'}}function IsConstructor(t){return'object'===Type(t)&&('function'==typeof t&&!!t.prototype)}function SpeciesConstructor(e,o){var r=Get(e,'constructor');if(r===undefined)return o;if('object'!==Type(r))throw new TypeError('O.constructor is not an Object');var n='function'==typeof self.Symbol&&'symbol'==typeof self.Symbol.species?r[self.Symbol.species]:undefined;if(n===undefined||null===n)return o;if(IsConstructor(n))return n;throw new TypeError('No constructor found')}!function(){var t=Function.prototype.bind.call(Function.prototype.call,Promise.prototype.then),o=function(t,o){return new t(function(t){t(o())})};CreateMethodProperty(Promise.prototype,'finally',function(e){var r=this;if('object'!==Type(r))throw new TypeError('Method %PromisePrototype%.finally called on incompatible receiver '+Object.prototype.toString.call(r));var n=SpeciesConstructor(r,Promise);if(!1===IsCallable(e))var i=e,c=e;else i=function(r){return t(o(n,e),function(){return r})},c=function(r){return t(o(n,e),function(){throw r})};return t(r,i,c)})}();})('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});",
                   /* Spread syntax for object literals helper (from babeljs.io) */ "function ownKeys(object,enumerableOnly){var keys=Object.keys(object);if(Object.getOwnPropertySymbols){var symbols=Object.getOwnPropertySymbols(object);if(enumerableOnly) symbols=symbols.filter(function(sym){return Object.getOwnPropertyDescriptor(object,sym).enumerable});keys.push.apply(keys,symbols)} return keys} function _objectSpread(target){for(var i=1;i<arguments.length;i++){var source=arguments[i]!=null?arguments[i]:{};if(i%2){ownKeys(Object(source),!0).forEach(function(key){_defineProperty(target,key,source[key])})}else if(Object.getOwnPropertyDescriptors){Object.defineProperties(target,Object.getOwnPropertyDescriptors(source))}else{ownKeys(Object(source)).forEach(function(key){Object.defineProperty(target,key,Object.getOwnPropertyDescriptor(source,key))})}} return target} function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0})}else{obj[key]=value} return obj}",
                  ]

for (polyfill of polyfills) {
  const scriptElement = document.createElement('script');
  scriptElement.textContent = polyfill;
  const parentElement = document.head || document.documentElement;
  parentElement.insertBefore(scriptElement, parentElement.firstChild);
}

window.addEventListener('beforescriptexecute',
  event => {
    let originalScript = event.target;

    if(/\/wizardhome\.js(\?.*)?$/.test(originalScript.src))
    {
      replaceScript(event, fixupWizardHome);
    }
  }
);

function fixupWizardHome(aInput) {
  return aInput.replace('{...params}', '_objectSpread({}, params)');
}

function replaceScript(aBeforeScriptEvt, aFixupScriptCallback) {
  aBeforeScriptEvt.preventDefault();
  aBeforeScriptEvt.stopPropagation();
  let originalScript = aBeforeScriptEvt.target;
  let response = GM_xmlhttpRequest({
    method: "GET",
    url: originalScript.src,
    synchronous: true
  });
  text = aFixupScriptCallback(response.responseText);

  let replacementScript = document.createElement('script');
  replacementScript.textContent = text;
  if (originalScript.hasAttribute('id')) {
    replacementScript.id = originalScript.id;
  }
  originalScript.parentNode.replaceChild(replacementScript, originalScript);
}
 
Keine Ursache. Zum 'Hänger' hatte ich noch eine Vermutung, die sich tatsächlich bewahrheitet hat – es lag daran, das GM_xmlhttpRequest() standardmäßig asynchron funktioniert
Das läuft jetzt absolut 1A. Meinen herzlichsten Dank, Du bist echt super. ;)
 
Hallo,

erst einmal sorry, dass ich den doch etwas betagten Thread wieder hochhole.

Aber mit dem zukünftigen Update auf FW 7.50 bzw. den Labor oder Inhaus 7.39 Firmwares wird oder ist dieses Thema wieder aktuell - zumindest für mich.

Auf unserer Hofstelle, die nicht bewohnt ist, werkelt eine 7590 ax. Zur Administrierung habe ich ein iPad Air (erste Generation), das nicht mehr mit dem aktuellen IOS versorgt wird. Optisch und technisch Top, und sogar der Akku ist noch in Ordnung.

Wenn ich mich mit der mit dem Tablet auf die FritzBox mit der Labor FW einloggen möchte, bekomme ich die Meldung, dass mein Browser (Safari) zu alt oder inkompatibel ist. Möchte ich aus dem Appstore einen neuen Browser laden und installieren, bekomme ich eine Meldung, dass ich eine ältere Version nutzen kann bzw. muss. Leider sind alle getesteten Browser (Edge, Opera, Mercury usw.) zu alt für AVM und lassen mich nicht auf die GUI.

Gibt es eine Möglichkeit, mein Ipad mit alten IOS und Browser noch weiter zu nutzen?

Ich habe mir mehrere AD Block pro, plus usw. runtergeladen, aber finde keine Möglichkeit die hier beschriebene Variante mit "fritz.box/browser.js" zu nutzen oder einzugeben.

Evtl. stelle ich mich einfach nur zu blöd an.

Wäre super, wenn mir jemand einen Workaround beschreiben könnte, ohne mir (wieder) ein neues Tablet kaufen zu müssen, um die Box damit administrieren zu können.

Danke

Roland
 
Javascript:
var ok = true;
var nbc = gNbc || false;
try {
  if (!nbc) {
    ok = ok && window.Proxy && typeof new window.Proxy({
    }, function () {
    }) === 'object';
    [
      '1'
    ].forEach(function () {
    });
    ok = ok && window.Promise && typeof new window.Promise(function () {
    }) === 'object';
    ok = ok && window.Blob && typeof new window.Blob(['<a></a>'], {
      type: 'text/html'
    }) === 'object';
    ok = ok && window.requestAnimationFrame && true;
    ok = ok && window.Promise.resolve(true).finally(function () {
    });
    ok = ok && (typeof window.BigInt('1') === 'bigint');
  }
} catch (err) {
  ok = false;
}
if (!ok) {
  window.location.href = 'sorry.lua';
}
So sieht die browser.js in der aktuellen Labor-Reihe aus.

Neu ist der Test auf bigint: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

Witzigerweise wird aber (bis zur 96346) außer diesem Test auf das Vorhandensein des Features diese Funktionalität (noch?) gar nicht weiter genutzt ... wer also die browser.js auf der Box wieder so ändert, daß dieser Test auf bigint nicht erfolgt, der kann (vorerst) auch ohne eingeschränkte Funktionalität weiterhin mit einem Browser arbeiten, der den bigint-Wrapper nicht unterstützt.

Ob das dann auch "live" möglich ist (Tampermonkey soll angeblich auch unter i(Pad)OS funktionieren, wobei da keine Angabe der Versionsnummer steht) und damit ohne Modifikationen an der Firmware, weiß ich auch nicht - ich wollte nur die "Grundlage" liefern, warum das (in den aktuellen Versionen) ggf. nicht mehr funktioniert.

Hier bräuchte man dann auch nicht PolyFill o.ä. "nachbauen", sondern lediglich den zusätzlichen Test auf bigint blockieren. Selbst wenn AVM das ggf. noch irgendwo nutzen wollte (vielleicht auch erst in der nächsten Version), dürften es nicht gleich alle Stellen in der Firmware sein, die dann nicht mehr funktionieren ... außerdem könnte/müßte AVM entsprechende Exceptions, wenn ein Objekt nicht erstellt werden kann, ordentlich abfangen können, so daß nicht gleich der komplette Prozess abbricht.

Aber nun kommt - zugegebenermaßen erst am Ende, damit das davor auch gelesen wird - die gute Nachricht ... wie man oben im JS-Code sehen kann, gibt es mit der Variablen nbc auch eine Möglichkeit, diese Browser-Checks zu überspringen (das nbc dürfte für no browser check stehen).

Wenn man den Aufruf der Start-Seite (bzw. der Login-Seite) also um den Parameter nbc ergänzt (der Wert spielt keine Geige, nur dessen Existenz), dann sollte sich das FRITZ!OS-GUI auch mit einem älteren Browser aufrufen lassen. Wie man Parameter im "querystring" eines HTTP-Requests angibt, verrät eine Internet-Suche.

EDIT: Wobei meine Suche nach der Verwendung von bigint-Objekten durch AVM nur die explizite Benutzung des Typs beinhaltete ... wenn da irgendwo noch "Konstanten" vorhanden sein sollten (also Zahlen, denen ein n als Typ hinten angefügt wurde), dann wurden die bei meinem grep nicht berücksichtigt.
 
Zuletzt bearbeitet:
  • Like
Reaktionen: Exodus88
Hat es schon irgendjemand geschafft mit Firefox ESR nach dem 7.50 Update auf die Fritzbox Oberfläche zu kommen? Der alte Weg geht bei mir leider nicht mehr. Auch https://fritz.box/?nbc=1 klappt leider nicht. Danke
 
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.