Libgourou v0.8.1

Saturday, 21 January 2023
Écrit par
Grégory Soutadé

Reminder : Libgourou is a free ADEPT protocol implementation (ePub DRM management from Adobe) that helps download ACSM files on Linux system (and remove DRM).

Libgourou v0.8.1 is out now. It's a minor release if we only look at the ChangeLog, but a very intersting one for a lot of aspects. First, the ChangeLog :

  • DRM with encryption key size 192 bits now fully supported by adept_remove
  • New -D option to specify .adept directory
  • Check for user ID before trying to decrypt a file
  • Default ADEPT directory is now /home/USER/.config/adept and can be specified by $ADEPT_DIR environment variable
  • -f option can be omitted and is replaced by last argument (ie: we can do ./acsmdownloader EPUB)
  • Add man pages
  • Add install/unintall and install_headers/uninstall_headers Makefile targets
  • PugiXML is no more statically linked, we use the system level shared library

Except one bug fix which add a major feature and new default path for .adept, all work has been done in Makefile part which is not code related. And this is interesting because it enlight the fact that libgourou is becoming a popular software (535 downloads within 4 months for v0.8), in "concurrence" with Knock (command line) and Calibre's plugin DeACSM (GUI). I get feedback from 5 different peoples that creates a port to MacOS, create packages for Gentoo and OpenSuse (ArchLinux has an outdated package) + a docker version. The reference implementation (utils) is becoming the only implementation and now has to be more user friendly. This is unexpected as, initially, the project has been designed as a library (so the name "lib" gourou) that should have been integrated by embedded devices, and a reference implementation to be used for Linux users. But I didn't expected that so many people were interested by the command line interface. If the project is still growing like that, I have no doubt that people will ask for new nice features, so wait and see !

You can find binary packages (compiled + AppImage) here.

IWLA 0.6

Sunday, 20 November 2022
Écrit par
Grégory Soutadé

Capture d'écran IWLA

Almost 3 years since the last news about IWLA. It does not really reflect the continuous development & maintenance of this wonderful tool. But don't worry, version 0.6 is now out ! The main change is the complete move from Python 2 to Python 3, but we may also mention :

  • Users requests are no more saved (except if keep_requests is set) which allow to save a LOT of space
  • A favicon is available
  • Fresh synchronization with AWSTATS data
  • Users need to do at least one hit per viewed page to not be marked as a robot
  • Feed detector has been enhanced
  • Track users plugin has been replaced by filter users which allows to define complex filters
  • Users can be enlighted in all visits page
  • IP can be anonymized (for public statistics)

The full ChangeLog is available here

While working on it, I realized how we can easily extend it. It's a real pleasure comparing to so big one PERL file code of AWSTATS, plus having it modular allows to implement our own rules which makes statistics really more precise. The only issue compared to AWSTATS is that IWLA is only focused on web statistics, but it has been design for it, not for everything related to log parsing !

New : A demo instance (for is available here

I also decided to give up the old style branching model with master and dev. Using git and its lightweight branches, it's better to have a model with tags for stable releases and features branch for development. Code is not often updated and it makes no sense to have a master branch updated every 3 years with only one merge commit while dev is living.

I recently had look on concurrence, especially with Matomo and I was really afraid to see how users are tracked ! Everything is managed from pages viewed to cursor moves, user system information retrieval, time spent... All of this generate extra traffic and requires to execute Javascript code to obtain a lot of information about users's environment. But it's not the worst tool as it doesn't use commercial tracking (like Google Analytics) and keep data on webmaster's server and it's certified RGPD compliant. Commercial trackers are really a nightmare for consumer's privacy. Using it, webmaster can obtain really good statistics, but everything is stored on (abroad) commercial servers to create your profile ! Your profile is then sold or used to display you personalized advertising. Unfortunately, almost all websites are using them. In opposite, IWLA requires no cookies, no Javascript, no awful banner. It only parse and analyze log requests from webserver and generate a static HTML report which is the only right way to do !

Virtual gift card in javascript

Sunday, 16 October 2022
Écrit par
Grégory Soutadé

For a birthday I wanted to offer a gift card (something to buy online or later). As I don't have a printer, I decided to create a simple web page containing this card. The address has to be flashed by a Qr Code. But, instead of directly display the gift, I wanted to have something that the person has to discover progressively.

With a little bit of javascript and thanks to HTML5 Canvas API, we can do it easily ! The idea is to create a canvas and then fill the blurred gift or a gift paper. When the person click and drag the mouse over the card, it progressively draw the clear gift card.

Here, I hardcoded some values, but it's possible to get them from image details and do it fully dynamic (Canvas API allows to scale drawn pictures in drawImage() method). Some parts of the code is just a copy/paste from Internet (sorry for copyright, I didn't save the link).

Or the same image with a gift paper :

Javascript source code :

    <canvas id="canvas" width="400" height="200" style="cursor:url(cursor32.png), auto ;">
      var canvas = document.getElementById('canvas');
      var ctx = canvas.getContext('2d');
      var rect = {};
      var drag = false;
      var imageObj = null, image2Obj = null;

      function init() {
          imageObj = new Image();

          // Gift paper version
          imageObj.onload = function () { ctx.drawImage(imageObj, 0, 0); };
          imageObj.src = 'paper.jpg';

          // Blur version
          imageObj.onload = function () { ctx.filter = 'blur(15px)'; ctx.drawImage(imageObj, 0, 0); ctx.filter = 'none'; };
          imageObj.src = 'gift.jpg';

          // Next
          image2Obj = new Image();
          image2Obj.src = 'gift.jpg';

          canvas.addEventListener('mousedown', mouseDown, false);
          canvas.addEventListener('mouseup', mouseUp, false);
          canvas.addEventListener('mousemove', mouseMove, false);
          canvas.addEventListener('touchstart', touchStart, false);
          canvas.addEventListener('touchmove', touchMove, false);

      function drawClearImage(x, y)
          var canvasRect = canvas.getBoundingClientRect();
          rect.startX = x - canvasRect.left - 5;
          rect.startY = y - - 5;
          if (rect.startX < 0) rect.startX = 0;
          if (rect.startY < 0) rect.startY = 0;

          ctx.drawImage(image2Obj, rect.startX, rect.startY, 40, 40, rect.startX, rect.startY, 40, 40);
      function mouseDown(e) {
          drag = true;
          drawClearImage(e.clientX, e.clientY);

      function mouseUp(e) { drag = false; }

      function mouseMove(e) {
          if (drag)
              drawClearImage(e.clientX, e.clientY);

      function drawClearImageForTouch(x, y)
          var canvasRect = canvas.getBoundingClientRect();
          rect.startX = x - canvasRect.left - 60;
          rect.startY = y - - 60;
          if (rect.startX < 0) rect.startX = 0;
          if (rect.startY < 0) rect.startY = 0;
          ctx.drawImage(image2Obj, rect.startX, rect.startY, 120, 120, rect.startX, rect.startY, 120, 120);

      function touchStart(e) {
          for (var i=0; i<e.changedTouches.length; i++)
              drawClearImage(e.changedTouches[i].clientX, e.changedTouches[i].clientY);

      function touchMove(e) {
          for (var i=0; i<e.changedTouches.length; i++)
              drawClearImage(e.changedTouches[i].clientX, e.changedTouches[i].clientY);



gPass 1.2

Saturday, 08 October 2022
Écrit par
Grégory Soutadé

Logo gPass

Reminder : gPass is an online password manager. It's a free, open source and self hostable alternative to laspass. All of your passwords are stored encrypted on YOUR server and you're the only one to know the master key needed to decrypt them.

Some weeks ago I received an email from Chrome's team asking me to remove one unused permission to gPass webextension with a delay of 14 days. It makes me see that manifest v2 will not be supported starting 2023, so I decided to migrate my extension to manifest v3. What a hell ! A lot of things changed with apparently no reason. After struggling a long week trying only yo keep the same functionalities, I was able to submit a new version !

So, main changes since v1 are :

Server side :

  • Remove old v1 crypto
  • When decrypting a password for a specific website, go to the entry
  • New UI (the first one was very ugly)
  • You can filter results for masterkey validation (avoid to display all your passwords to everyone)
  • Add a button to copy password into clipboard
  • Change button's name instead of displaying an alert

Client side :

  • Update to manifest v3 (Chrome only)
  • Add an option to deactivate form's hook
  • Some bug fixes
  • Add a checkbox in popup to copy password into clipboard

Extensions are available here (Firefox) and there (Chrome). You can download server side on my project page.

Libgourou v0.8

Sunday, 11 September 2022
Écrit par
Grégory Soutadé

Reminder : Libgourou is a free ADEPT protocol implementation (from Adobe) that helps download ACSM files from Linux.

Good news, libgourou v0.8 is out now !

I missed to speak about it since v0.5 (april 2022), but a lot of work has been done :

  • Bug fixes, especially in PDF part
  • Qt has been replaced by libcurl (lighter & better display when downloading ePub)
  • Option to resume (big) downloads that may have failed
  • Manage loaned (and returnable) books
  • Migrate utils to OpenSSL 3
  • Integrate Base64 code into sources
  • Support for over encrypted private key when removing DRM (192 bytes keys)

Another improvement asked by a lot of people is the build of an AppImage. I don't really like it because it's big and you do not receive (security) updates from your package manager, but it allows to run on most of Linux platforms by embedding all necessary dependencies.