Skip to content
Snippets Groups Projects

Dolibarr user's scripts

  • Clone with SSH
  • Clone with HTTPS
  • Embed
  • Share
    The snippet can be accessed without any authentication.
    Authored by Florian Charlaix
    Edited
    security_code_breaker.user.js 3.13 KiB
    // ==UserScript==
    // @name        Dolibarr Security code breaker
    // @icon        https://www.dolibarr.org/medias/image/www.dolibarr.org/images/stories/dolibarr.png
    // @namespace   Open-DSI
    // @match       *://*/*
    // @version     2.0
    // @author      Florian Charlaix <fcharlaix@open-dsi.fr>
    // @description Use OCR to auto complete the Dolibarr security code on login page
    // @grant       GM.getValue
    // @downloadURL https://git.open-dsi.fr/-/snippets/5/raw/master/security_code_breaker.user.js
    // ==/UserScript==
    
    const code_re = new RegExp("^[A-z0-9]{5}$", "g");
    
    function log(msg) {
      console.log(`Dolibarr Security code breaker: ${msg}`);
    }
    
    log("loaded");
    
    function sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    function encodeQueryData(data) {
       const ret = [];
       for (let d in data)
         ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]));
       return ret.join('&');
    }
    
    function retry() {
      log("Retry !")
      document.getElementById("captcha_refresh_img").click();
    }
    
    function input_code(code) {
      log(`Code ${code}`);
      if (!code_re.test(code)) {
        log("Invalide code");
        return false;
      }
    
      document.getElementById("securitycode").value = code;
      return true;
    }
    
    async function getImageData() {
      let canvas = document.createElement('canvas');
      let context = canvas.getContext('2d');
      let data = null;
      while (!data && data != "data:,") {
        await sleep(1000);
        img = document.getElementById('img_securitycode');
        canvas.height = img.naturalHeight;
        canvas.width = img.naturalWidth;
        context.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight);
        data = canvas.toDataURL();
      };
      return data;
    }
    
    async function image2code(data) {
      const http = new XMLHttpRequest();
      http.open("POST", "https://api.ocr.space/parse/image");
      http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    
      params = {
        apikey: await GM.getValue("apiKey"),
        isOverlayRequired: false,
        detectOrientation: false,
        isTable: false,
        OCREngine: 2,
        scale: true,
        base64Image: data
      }
    
      http.addEventListener("error", event => {log(`API error ! ${http.status}`)});
    
      let promise = new Promise((ok) => {
        http.addEventListener("readystatechange", event => {
          if (http.readyState === 4) {
            let parsedText = JSON.parse(http.responseText).ParsedResults[0].ParsedText;
            parsedText = parsedText.split("\n")[0];
            ok(parsedText);
          }
        })
      });
    
      http.send(encodeQueryData(params));
    
      return await promise;
    }
    
    async function breakCode() {
      let data = await getImageData();
      let code = await image2code(data);
      if (!input_code(code)) {
        retry();
      }
      log("Code craked °3°");
    }
    
    function main() {
      let author = document.querySelector("meta[name='author']");
      if (!(author && (author.content === "Dolibarr Development Team" || "Easya & Dolibarr Development Team"))) {
        return;
      }
      log("It's a Dolibarr !");
    
      if (!document.getElementById('login')) {
        return;
      }
      log("And we are at the login page OwO");
    
      if (!document.getElementById('img_securitycode')) {
        return;
      }
      log("And a security code is present \\o/");
    
      setTimeout(breakCode, 10);
    }
    
    main();
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Finish editing this message first!
    Please register or to comment