FreeMobile TinyAuth

Retour à l'ancien mode d'identification sur FreeMobile.

// ==UserScript==
// @name           FreeMobile TinyAuth
// @namespace      freemobile
// @description    Retour à l'ancien mode d'identification sur FreeMobile.
// @include        https://mobile.free.fr/*
// @version        2.7.1
// @grant          all
// @run-at         document-start
// ==/UserScript==
(function () {

var version = "2.7.1";

var debug = false;
var imgs = [];
var isOpera = false;

var options = {
    timer: 1, // utiliser une temporisation avant l'envoi du formulaire (defaut: oui).
    timerSubmit : 2000 // temps de la temporisation.
}
try {
    if (!unsafeWindow) {
        unsafeWindow = window;
    }
} catch (e) {}

if (GM_getValue == undefined && window.localStorage != undefined) {
    var GM_getValue = function (name) {
        if (name in options) {
            var v = window.localStorage.getItem(name);
            if (v != null) {
                return v;
            }
            return options[name];
        }
        return null;
    };
}
if (GM_setValue == undefined && window.localStorage != undefined) {
    var GM_setValue = function (name, value) {
        if (name in options) {
            return window.localStorage.setItem(name, value);
        }
    };
}

var saveOptions = function () {
    for (option in options) {
        GM_setValue(option, options[option]);
    }
};
var loadOptions = function () {
    for (option in options) {
        options[option] = GM_getValue(option);
    }
};
loadOptions();

var convert_color = function (image_data) {
    for (var x = 0; x < image_data.width; x++) {
        for (var y = 0; y < image_data.height; y++) {
            var i = x*4+y*4*image_data.width;
            var luma = Math.floor(image_data.data[i] * 299/1000 +
            image_data.data[i+1] * 587/1000 +
            image_data.data[i+2] * 114/1000);

            image_data.data[i] = luma;
            image_data.data[i+1] = luma;
            image_data.data[i+2] = luma;
            image_data.data[i+3] = 255;
            if (image_data.data[i] > 200 || image_data.data[i+3] == 0) {
                image_data.data[i] = 255;
                image_data.data[i+1] = 255;
                image_data.data[i+2] = 255;
                image_data.data[i+3] = 0;
            }
        }
    }
};

if (debug) {
    var testDecode = function () {
        console.log("Start test ...");
        var canvas, ctx, imageData;
        var debugCanvas, debugCtx;
        var number, numbers = [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1];
        var debugCanvas = document.createElement("canvas");
        debugCanvas.setAttribute("width", 10*10);
        debugCanvas.setAttribute("height", 16);
        form.appendChild(debugCanvas);
        var debugCtx = debugCanvas.getContext('2d');
        canvas = document.createElement("canvas");
        canvas.setAttribute("width", 10);
        canvas.setAttribute("height", 16);
        ctx = canvas.getContext('2d');
        for (var i = 0; i < 10; i++) {
            var img = imgs[i];
            ctx.fillStyle = "rgb(255,255,255)";
            ctx.fillRect(0,0,10,16);
            ctx.drawImage(img, 14, 12, 10, 16, 0, 0, 10, 16);
            imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            number = get_numberV2(imageData);
            console.log(number, imageData);
            ctx.putImageData(imageData, 0, 0);
            debugCtx.drawImage(canvas, 0, 0, 10, 16, 10*i, 0, 10, 16);
        }
        console.log("Done.");
    };
}

var get_numberV1 = function(image_data) {
    convert_color(image_data);
    var idx = 34;
    var test = 0;
    for (var i = 0; i < 10; i++) {
        if (image_data.data[(idx+i*10)*4+3] > 0) {
            break;
        }
    }
    if (i == 10) { // 0
        return 0;
    }
    var idx = 6;
    for (var i = 0; i < 15; i++) {
        if (image_data.data[(idx+i*10)*4+3] == 0) {
            break;
        }
    }
    if (i == 15) { // 1 3 4 8 9
        idx = 103; // 4
        if (image_data.data[idx*4+3] > 0 && image_data.data[(idx+2)*4+3] > 0) {
            return 4;
        }
        idx = 34; // 1
        if (image_data.data[idx*4+3] > 0) {
            return 1;
        }
        idx = 102; // 9
        if (image_data.data[idx*4+3] == 0 && image_data.data[(idx+1)*4+3] == 0) {
            return 9;
        }
        idx = 92; // 3
        if (image_data.data[idx*4+3] == 0) {
            return 3;
        }
        return 8;
    }
    if (image_data.data[72*4+3] > 0 && image_data.data[92*4+3] == 0) { // 5
        return 5;
    }
    if (image_data.data[88*4+3] > 0) { // 6
        return 6;
    }
    if (image_data.data[42*4+3] > 0) {
        return 2;
    }
    return 7;
};

var get_numberV2 = function(image_data) {
    convert_color(image_data);
    var idx = 34;
    var test = 0;
    for (var i = 0; i < 10; i++) {
        if (image_data.data[(idx+i*10)*4+3] > 0) {
            break;
        }
    }
    if (i == 10) { // 0
        return 0;
    }
    var idx = 6;
    for (var i = 0; i < 15; i++) {
        if (image_data.data[(idx+i*10)*4+3] == 0) {
            break;
        }
    }
    if (i == 15) { // 1 3 4
        idx = 103; // 4
        if (image_data.data[idx*4+3] > 0 && image_data.data[(idx+2)*4+3] > 0) {
            return 4;
        }
        idx = 34; // 1
        if (image_data.data[idx*4+3] > 0) {
            return 1;
        }
        idx = 92; // 3
        if (image_data.data[idx*4+3] == 0) {
            return 3;
        }
    }
    if (image_data.data[72*4+3] > 0 && image_data.data[92*4+3] == 0) { // 5
        return 5;
    }
    if (image_data.data[88*4+3] > 0) { // 6 8 9
        if (image_data.data[61*4+3] == 0) {
            return 8;
        }
        if (image_data.data[101*4+3] == 0) {
            return 9;
        }
        return 6;
    }
    if (image_data.data[42*4+3] > 0) {
        return 2;
    }
    return 7;
};

var decodeV1 = function () {
    if (debug) {
        console.log("Decodeur V1");
    }
    var canvas, ctx, imageData;
    var debugCanvas, debugCtx;
    var number, numbers = [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1];
    // start debug
    if (debug) {
        var debugCanvas = document.createElement("canvas");
        debugCanvas.setAttribute("width", 10*10);
        debugCanvas.setAttribute("height", 16);
        form.appendChild(debugCanvas);
        var debugCtx = debugCanvas.getContext('2d');
    }
    // end debug
    canvas = document.createElement("canvas");
    canvas.setAttribute("width", 10);
    canvas.setAttribute("height", 16);
    ctx = canvas.getContext('2d');
    for (var i = 0; i < 10; i++) {
        var img = imgs[i];
        ctx.fillStyle = "rgb(255,255,255)";
        ctx.fillRect(0,0,10,16);
        ctx.drawImage(img, 14, 12, 10, 16, 0, 0, 10, 16);
        imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        number = get_numberV1(imageData);
        // start debug
        if (debug) {
            console.log(number);
            ctx.putImageData(imageData, 0, 0);
            debugCtx.drawImage(canvas, 0, 0, 10, 16, 10*i, 0, 10, 16);
        }
        // end debug
        if (number < 0 || number > 9 || numbers[number] != -1) {
            throw new Error("Décodage échoué.");
        }
        if (number != undefined) {
            numbers[number] = i;
        }
    }
    return numbers;
};

var decodeV2 = function () {
    if (debug) {
        console.log("Decodeur V2");
    }
    var canvas, ctx, imageData;
    var debugCanvas, debugCtx;
    var number, numbers = [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1];
    // start debug
    if (debug) {
        var debugCanvas = document.createElement("canvas");
        debugCanvas.setAttribute("width", 10*10);
        debugCanvas.setAttribute("height", 16);
        form.appendChild(debugCanvas);
        var debugCtx = debugCanvas.getContext('2d');
    }
    // end debug
    canvas = document.createElement("canvas");
    canvas.setAttribute("width", 10);
    canvas.setAttribute("height", 16);
    ctx = canvas.getContext('2d');
    for (var i = 0; i < 10; i++) {
        var img = imgs[i];
        ctx.fillStyle = "rgb(255,255,255)";
        ctx.fillRect(0,0,10,16);
        ctx.drawImage(img, 14, 12, 10, 16, 0, 0, 10, 16);
        imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        number = get_numberV2(imageData);
        // start debug
        if (debug) {
            console.log(number);
            ctx.putImageData(imageData, 0, 0);
            debugCtx.drawImage(canvas, 0, 0, 10, 16, 10*i, 0, 10, 16);
        }
        // end debug
        else if (number < 0 || number > 9 || numbers[number] != -1) {
            throw new Error("Décodage échoué.");
        }
        if (number != undefined) {
            numbers[number] = i;
        }
    }
    return numbers;
};

var decodeSND = function () {
    if (debug) {
        console.log("Decodeur via le son");
    }
    var number, numbers = [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1];
    var map = {
        "17135": 0,
        "9825":  1,
        "15045": 2,
        "16299_3": 3,
        "16299_4": 4,
        "18807": 5,
        "18389": 6,
        "17971": 7,
        "16717": 8,
        "17553": 9
    };
    var soundManager = unsafeWindow.soundManager;
    if (undefined == soundManager) {
        throw new Error("Décodage échoué.");
    }
    for (var i = 0; i < 10; i++) {
        if (!soundManager.getSoundById("sound"+i)) {
            throw new Error("Décodage échoué.");
        }
        var bytes = soundManager.getSoundById("sound"+i).bytesTotal;
        if (bytes == 16299) {
            if (numbers[3] > -1) {
                number = 4;
            } else if (numbers[4] > -1) {
                number = 3;
            } else {
                canvas = document.createElement("canvas");
                canvas.setAttribute("width", 10);
                canvas.setAttribute("height", 16);
                ctx = canvas.getContext('2d');
                var img = imgs[i];
                ctx.fillStyle = "rgb(255,255,255)";
                ctx.fillRect(0,0,10,16);
                ctx.drawImage(img, 14, 12, 10, 16, 0, 0, 10, 16);
                imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                number = get_numberV2(imageData);
            }
        } else {
            number = map[bytes];
        }
        if (number < 0 || number > 9 || numbers[number] != -1) {
            throw new Error("Décodage échoué.");
        }
        if (debug) {
            console.log("Sound "+i+" => "+number);
        }
        numbers[number] = i;
    }
    return numbers;
};

var decode = function () {
    var numbers;
    var ok = false;
    try {
        numbers = decodeV2();
        ok = true;
    } catch (e) {}
    if (!ok) {
        try {
            numbers = decodeV1();
            ok = true;
        } catch (e) {}
    }
    if (!ok) {
        try {
            numbers = decodeSND();
            ok = true;
        } catch (e) {}
    }
    if (!ok) {
        throw new Error("Décodage échoué.");
    }
    return numbers;
};

var form;
var hiddePanel = function () {
    form.addEventListener("submit", sendForm, true);
    var els = form.querySelectorAll("*");
    for (var j = 1; j < els.length; j++) {
        if (els[j].tagName != "TABLE" && (form == els[j].parentNode || els[j].tagName == "SPAN")) {
            els[j].oldDisplay = els[j].style.display;
            els[j].style.display = "none";
        }
    }
    var label = document.querySelector("#content>span");
    if (label) {
        label.style.display = "none";
    }
    var buttonsContainer = document.querySelector(".ident_chiffre2");
    if (buttonsContainer) {
        buttonsContainer.style.display = "none";
    }
    var submit = document.querySelectorAll("form button[type=submit]")[0];
    if (submit) {
        submit.parentNode.style.display = "block";
    }
};

var displayPanel = function () {
    form.removeEventListener("submit", sendForm, true);
    var els = form.querySelectorAll("*");
    for (var j = 1; j < els.length; j++) {
        if (els[j].tagName != "TABLE" && (form == els[j].parentNode || els[j].tagName == "SPAN")) {
            els[j].style.display = "block";
        }
    }
    var label = document.querySelector("#content>span");
    if (label) {
        label.style.display = "block";
    }
    var buttonsContainer = document.querySelector(".ident_chiffre2");
    if (buttonsContainer) {
        buttonsContainer.style.display = "block";
    }
};

var count = 0;
var timerSubmit = function () {
    var realTimer = parseInt(options.timerSubmit) + 500;
    if (options.timer == 0) {
        document.getElementById("msgSubmit").innerHTML = "Connexion en cours (normalement) ...";
        return;
    }
    if (count >= realTimer) {
        count = 0;
        document.getElementById("msgSubmit").innerHTML = "Connexion en cours (normalement) ...";
        return;
    }
    count += 1000;
    if (count > realTimer) {
        count = realTimer;
    }
    document.getElementById("msgSubmit").innerHTML = "Connexion dans "+parseInt((realTimer - count) / 1000)+" secondes ...";
    setTimeout(timerSubmit, 1000);
};

var ready = 0;
var timerImagesSmall = function (numbers) {
    ready = 0;
    var id = document.getElementById("ident_login").value.split("");
    document.getElementById("msgSubmit").style.display = "block";
    timerSubmit();
    var fnReady = function () {
        ready += 1;
        if (ready == 9) {
            document.getElementById("msgSubmit").style.display = "block";
            form.submit();
        } else if (ready < 9) {
            if (options.timer == 1) {
                setTimeout(loadNext, 500);
            }
        }
    };
    var cursor = 0;
    var loadNext = function () {
        var img = document.createElement("img");
        img.onload = fnReady;
        img.src = "chiffre.php?pos="+numbers[id[cursor]]+"&small=1";
        img.style.visibility = "hidden";
        document.body.appendChild(img, document.getElementById("ident_login"));
        cursor++;
    };
    if (options.timer == 0) {
        for (var j = 0; j < 10; j++) {
            loadNext();
        }
    } else {
        loadNext();
    }
};

var sendForm = function (e) {
    if (debug || ready < 8) {
        e.preventDefault();
    }
    if (ready == 8) {
        return;
    }
    var newInput = document.getElementById("ident_login");
    var numbers;
    try {
        numbers = decode();
    } catch(e) {
        displayPanel();
        var span = document.createElement("span");
        span.innerHTML = 'Détection automatique impossible : <a href="https://github.com/Blount/FreeMobile_TinyAuth">surveillez les mises à jour</a>.';
        span.style.fontWeight = "bold";
        document.getElementById("ident_blocd").insertBefore(span,
            document.getElementById("ident_div_ident"));
        newInput.parentNode.removeChild(newInput);
        return;
    }
    var ident = "";
    var n, id = newInput.value.split("");

    for (var j = 0; j < id.length; j++) {
        n = parseInt(id[j]);
        if (n >= 0 && n <= 9) {
            ident += numbers[n];
        }
    }
    timerImagesSmall(numbers);
    newInput.setAttribute("name", "");
    document.getElementById("ident_pos").value = ident;
};

var drawScriptPanel = function () {
    isOpera = window.navigator.appName.match("Opera");
    // custom CSS
    var style = document.createElement("style");
    style.setAttribute("type", "text/css");
    style.innerHTML  = "<!-- ";
    style.innerHTML += " .tinyAuthContainer {position: absolute; top: 0; right: 20px; text-align: center; ";
    style.innerHTML += " padding: 5px 20px; background: #F5F5F5; border: 2px solid #DDDDDD; box-shadow: 0 0 5px #CCC; }";
    style.innerHTML += " .tinyAuthContainer a:link, .tinyAuthContainer a:hover, .tinyAuthContainer a:active, .tinyAuthContainer a:visited {";
    style.innerHTML += " color: #333333; font-weight: bold;}";
    style.innerHTML += " .tinyAuthContainer span.title { font-weight: bold; color: #EF0000; }";
    style.innerHTML += " .tinyAuthContainer div.infos input { background: #F0F0F0; border: 1px solid #E5E5E5; color: #333333; border-radius: 4px; font-size: 9px; cursor: pointer; }";
    style.innerHTML += " .tinyAuthContainer .options {text-align: left; ";
    style.innerHTML += " padding: 5px 20px; background: #FFFFFF; border: 2px solid #DDDDDD; display: none; }";
    style.innerHTML += " -->";
    document.head.appendChild(style);

    var url = isOpera?"http://ilatumi.org/FreeMobile_TinyAuth.oex":"https://github.com/Blount/FreeMobile_TinyAuth/raw/master/freemobile_tinyauth.user.js";
    var container = document.createElement("div");
    container.setAttribute("class", "tinyAuthContainer");
    var contentHTML = "";
    contentHTML += '<span class="title">TinyAuth '+version+'</span> : <a href="https://github.com/Blount/FreeMobile_TinyAuth">Home</a> | ';
    contentHTML += '<a href="'+url+'">';
    contentHTML += '<img src="http://ilatumi.org/tinyauth-freemobile/version.php?v='+version+'" alt="Test de version en cours …" style="vertical-align: middle;" /></a>';
    contentHTML += '<div class="infos">';
    contentHTML += '    <input type="button" value="Afficher le pavé numérique" id="togglePanel" />';
    contentHTML += '    <input type="button" value="+ options" id="tinyAuthtoggleOptions" />';
    contentHTML += '</div>';
    contentHTML += '<div class="options" id="tinyAuthOptionsContainer">';
    contentHTML += '<label><input type="checkbox" name="timer" id="tinyAuth-active-timer" value="1" class="clickclick" /> activer le temps d\'attente avant connexion</label>';
    contentHTML += '<p style="text-align: center; margin:0;"><input type="button" id="tinyAuth-closeoptions" value="OK" />';
    contentHTML += '</div>';
    container.innerHTML = contentHTML;
    var header = document.getElementById("header");
    if (!header) {
        header = document.head;
    } else {
        header.style.position = "relative";
    }
    document.getElementById("header").appendChild(container);
    document.getElementById("togglePanel").addEventListener("click", function () {
        if (form.querySelectorAll("span.red")[0].style.display == "none") {
            this.value = "Masquer le pavé numérique";
            displayPanel();
        } else {
            this.value = "Afficher le pavé numérique";
            hiddePanel();
        }
    }, false);
    var toggleOptions = function () {
        if (document.getElementById("tinyAuthOptionsContainer").style.display != "block") {
            document.getElementById("tinyAuthOptionsContainer").style.display = "block";
        } else {
            document.getElementById("tinyAuthOptionsContainer").style.display = "none";
        }
    };
    document.getElementById("tinyAuthtoggleOptions").addEventListener("click", toggleOptions, false);
    document.getElementById("tinyAuth-closeoptions").addEventListener("click", toggleOptions, false);
    var els = container.querySelectorAll(".clickclick");
    for (var i = 0; i < els.length; i++) {
        els[i].addEventListener("click", function (e) {
            var type = this.getAttribute("type");
            if (type == "checkbox") {
                options[this.getAttribute("name")] = this.checked?1:0;
            }
            saveOptions();
        }, false);
    }
    for (option in options) {
        var el = container.querySelectorAll("*[name="+option+"]");
        if (el.length) {
            var type = el[0].getAttribute("type");
            if (type == "checkbox") {
                el[0].checked = options[option] != 0?"checked":"";
            }
        }
    }
};
var start = function () {
    if (!document.getElementById("ident_pos")) {
        return;
    }
    //~ document.body.appendChild(customForm);
    drawScriptPanel();
    var forms = document.getElementsByTagName("form");
    if (forms.length > 0) {
        for (var k = 0; k < forms.length; k++) {
            var submit = forms[k].querySelectorAll("form button[type=submit]")[0];
            if (forms[k].style.display != "none" && submit && submit.style.display != "none") {
                form = forms[k];
            }
        }
    }
    var imgsEl = document.querySelectorAll(".ident_chiffre2 li img");
    for (var i = 0; i < imgsEl.length; i++) {
        var attr = imgsEl[i].getAttribute("onmouseover");
        if (attr && false != attr.indexOf("getVoiceStatus")) {
            imgs.push(imgsEl[i]);
        }
    }
    var identPos = document.getElementById("ident_pos");
    var newInput = document.createElement("input");
    newInput.setAttribute("type", "text");
    newInput.setAttribute("id", "ident_login");
    newInput.setAttribute("autocomplete", "On");
    newInput.setAttribute("name", "ident_login");
    identPos.parentNode.appendChild(newInput);
    var msgSubmit = document.createElement("p");
    msgSubmit.setAttribute("id", "msgSubmit");
    msgSubmit.style.display = "none";
    msgSubmit.style.fontWeight = "bold";
    msgSubmit.style.textAlign = "right";
    msgSubmit.style.clear = "both";
    form.appendChild(msgSubmit);
    hiddePanel();
};

if (typeof unsafeWindow != "undefined") {
    document.addEventListener ("readystatechange", function () {
        if (document.readyState == "interactive") {
            start();
        }
    }, true);
} else {
    document.addEventListener("DOMContentLoaded", start, false);
}

})();