Why SourceForge should not die today

With the recent downtime of SourceForge we can read comment like:

  • Sourceforge should die
  • Someone still use sourceforge?
  • Sourceforge is a place with only malware
  • All active projects are already on Github
  • Nobody will notice if Sourceforge disapear

It’s wrong. If sourceforge disapear the transition will be annoying.

Sourceforge exist since a long time and even if we don’t know a lot of project still use it especially for the download mirror service. Some are actively maintain and can move, but some are abandoned and will be lost forever even if they still have users.

You disagree with me?

Take a look on where Homebrew formula download their source code or patches.

  • We have 3157 formula
  • 527 formulas use downloads.sourceforge.net (grep ".*url.*downloads.sourceforge.net" * | cut -d":" -f1|sort|uniq|wc -l)
  • 888 use Github (grep ".*url.*https://github.com/" * | cut -d":" -f1|sort|uniq|wc -l)
  • 113 for google code (grep ".*url.*googlecode.com" * | cut -d":" -f1|sort|uniq|wc -l)

Even if it’s not the majority we can’t say we can just ignore it.

But it’s only dead and unused project.

If we have a quick look on the list of this minor/dead project. We can found some pretty common software:

  • avidemux
  • boost
  • clamav
  • gnuplot
  • lame
  • netcat
  • pngcrush
  • proguard
  • privoxy
  • pwgen
  • swig
  • w3m
  • wxpython
  • zsh

And homebrew contain only project working on OSX and where someone has taken the time to package it.

We can survive to a lost of sourceforge website for the downloads, thanks to large number a sourceforge mirror. But for source repository, mailling list archive all of this can be lost. If SourceForge die for financial issues a risk exists that the investors will try to sell this archives instead of transferring for free to a foundation like Apache or Mozilla.

Also if tomorrow sourceforge die, how can you be sure that the github repository of a sourceforge project is made by the same team?

We need to prepare a smooth transition from Sourceforge. Why the parent compagnie of Sourceforge should continue to put money on a dying website? They are a for profit organization. In my mind the best solution is transfering a read only version to a non profit organisation. And because the same issue could happen with GitHub we need to work to decentralize free software hosting. It’s critical for the Free Software world, but also for all compagnies using this technologies.

Photo: Mark Lobo Licence CC BY-NC-ND 2.0

Reverse on OSX

This articles is a simple collection of programm I use for understanding how a third party programm interact with the system.

List symbols of a binary

nm -g /bin/ls
                 U __DefaultRuneLocale
                 U ___assert_rtn
                 U ___bzero
                 U ___error
                 U ___maskrune
                 U ___snprintf_chk
                 U ___stack_chk_fail
                 U ___stack_chk_guard

 Show shared libraries used by a programm

otool -L /bin/ls
	/usr/lib/libutil.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libncurses.5.4.dylib (compatibility version 5.4.0, current version 5.4.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)

Get asm code

otool -vt /bin/ls

List open file and network connections

COMMAND     PID            USER   FD      TYPE             DEVICE   SIZE/OFF     NODE NAME
launchd       1            root  cwd       DIR                1,2       1224        2 /
launchd       1            root  txt       REG                1,2     304240 21153870 /sbin/launchd

Based on Dtrace

dtrace is a powerfull tools for reverse engineer


iosnoop is a live trace of disk/io

sudo iosnoop
  501 88892 R 440836400   4096 Google Chrome ??/Cache/data_2
  501 88892 R 420909232   4096 Google Chrome ??/Cache/data_0
  501 88892 R 439174816   4096 Google Chrome ??/Cache/data_2


Live trace file opening

sudo opensnoop -ve
STRTIME                UID    PID COMM          FD ERR PATH
2015 May 11 13:51:00     0     99 DisplayLinkMana   6   0 /Library/Application Support/DisplayLink/.dl.xml
2015 May 11 13:51:00     0     99 DisplayLinkMana   6   0 /Library/Application Support/DisplayLink/.dl.xml


Live trace program execution

sudo execsnoop
  501  52098  48099 sudo


dtruss allow you to show all system calls. You can filter by binary with the -n options.

sudo dtruss -n ls
	PID/THRD  SYSCALL(args) 		 = return
52383/0x1e98b4:  thread_selfid(0x7FFF5B281460, 0x7F93C18013F0, 0x7F93C060A7D0)		 = 2005172 0
52383/0x1e98b4:  csops(0x0, 0x0, 0x7FFF5BF4FA08)		 = 0 0
52383/0x1e98b4:  issetugid(0x0, 0x0, 0x7FFF5BF4FA08)		 = 0 0


Show system calls errors

sudo errinfo
            EXEC          SYSCALL  ERR  DESC
           iTerm             read   35  Resource temporarily unavailable
           iTerm             read   35  Resource temporarily unavailable
           iTerm             read   35  Resource temporarily unavailable

Migration from PyQT4 to PyQT5 at GNS3

The current GNS3 GUI interface use PyQT4. In order to support the retina display we choose to move to PyQT5.

The move was not too complicated with the help of a small script.

You can see the complete list of PyQT4 / PyQT5 differences here: http://pyqt.sourceforge.net/Docs/PyQt5/pyqt4_differences.html

Actually most of recent distributions support PyQT5:

  • Debian Jessie
  • Ubuntu 14.04 and later
  • Arch linux
  • Gentoo
  • Fedora 21 and later

In all our code we already not directly include the PyQT4 module but our own qt module responsible of all the imports this save us the need to patch every files for changing the module.

An annoying point was the move from QtGui to QtWidgets of a lot of element. That’s why we wrote a script finding all the call to QtGui and checking if the module as not move to QtWidgets. The clean syntax of Python allow us to write a naive script.

It’s very easy with this apply to each line of the file:

if "QtGui." in line:
    for name, obj in inspect.getmembers(QtWidgets):
        line = line.replace("QtGui." + name, "QtWidgets." + name)

After that you need to import also QtWidgets. All our imports was like:

from .qt import QtGui

It’s easy to patch it by code:

if line.startswith("from ") and "import" in self._line and "QtGui" in line and not "QtWidgets" in line:
    line = line.strip() + ", QtWidgets\n"

Thanks to the previous move to Python 3 fixing the call to parent classe was easy because we can replace:




Our script detect the name of parent classes and replace it by super.

Thanks to the script most of our code was working after this. We just need to check the script behavior by using git diff.

Also when using the app we have detected some issue. You need to know that method deprecated in QT5 are totaly removed in PyQT5. For us it was only a few calls.

Our patch script it’s specific for our code but can be a source of inspiration, if you want to use it you need to replace gns3 by your module. It’s also check if you haven’t a double init call:

import os
import sys
import re
import inspect
from PyQt5 import QtWidgets
class FilePatcher:
    def __init__(self, path):
        self._path = path
        self._line_number = 1
        self._previous_line = None
        self._line = None
        self._parent_classes = []
        self._qtwidgets_imported = False
    def error(self, msg):
        print("ERROR: {}:{} {}".format(self._path,self._line_number, msg))
    def info(self, msg , *args):
        msg = msg + " ".join(args)
        print("INFO: {}:{} {}".format(self._path,self._line_number, msg))
    def patch(self):
        out = ""
        with open(self._path) as f:
            previous_line = None
            for self._line in f.readlines():
                if self._previous_line:
                self._line_number += 1
                self._previous_line = self._line
                out += self._line
        with open(self._path, 'w+') as f:
    def get_parent_class(self):
        """Extract parent class to self._parent_classes var"""
        if self._line.startswith("class "):
            l = re.match(r".*\((.*)\):", self._line)
            if l:
                self._parent_classes = []
                for cls in l.group(1).split(","):
    def fix_object_inheritance(self):
        """In Python3 you no longer need to inherit from object"""
        if "(object):" in self._line:
            self._line = re.sub(r"\(object\)", "", self._line)
    def error_double_init(self):
        Detect double call to init and raise an error
        if ".__init__" in self._previous_line and ".__init__" in self._line:
            self.error("Double init is no longer allowed")
    def fix_super_with_argument(self):
        Thanks to Python 3 now we can call super() instead of super(MyClassParent)
        if re.match(r".*super\([^)].*", self._line):
            self._line = re.sub(r"super\([^)]+\)", "super()", self._line)
            self.info("Fix ", self._line.strip())
    def fix_init_with_self(self):
        In some part of the code we have MyClassParent.__init__(self

        Now we can use super().__init__
        if ".__init__(self" in self._line:
            self._line = re.sub(r"([A-Z\.a-z0-9_-]+)\.__init__\(self,? ?", "super().__init__(", self._line)
    def fix_call_without_super(self):
        We need to call parent with super instead of class name in order to avoid issues
        for cls in self._parent_classes:
            m = re.match(r"(.*)({})\.([a-zA-Z]+)\((self, ? ?)(.*)".format(cls), self._line)
            if m:
                fixed = m.group(1) + "super()." + m.group(3) + "(" + m.group(5) + "\n"
                self._line = fixed
    def fix_qt_widgets(self):
        Replace QtGui by QtWidgets when require
        if self._line.startswith("from ") and "import" in self._line and "QtGui" in self._line and not "QtWidgets" in self._line:
            self._line = self._line.strip() + ", QtWidgets\n"
        if "QtGui." in self._line:
            for name, obj in inspect.getmembers(QtWidgets):
                self._line = self._line.replace("QtGui." + name, "QtWidgets." + name)
    def error_import_missing(self):
        Check if we use QtWidgets without QtGui
        if "QtWidgets" in self._line:
            if " import " in self._line:
                self._qtwidgets_imported = True
                if self._qtwidgets_imported is False:
                    self.error("QtWidgets import missing")
for root, dirs, files in os.walk('gns3'):
  for file in files:
    if file.endswith('.py'):
        FilePatcher(os.path.join(root, file)).patch()

Lettre à mon Député

Monsieur le Député,

Suite à la lecture de votre article sur le projet de loi sur le renseignement: http://www.jeanluclaurent.fr/Liberticide_a423.html

Je tenais à vous faire part de mes inquiétudes concernant ce texte et de mes désaccords.

En premier lieu, vous indiquez que vous ne légiférez pas dans l’urgence. Cette affirmation est fausse. En effet, le Gouvernement utilise la procédure accélérée réduisant la possibilité pour vous d’effectuer votre travail de parlementaire dans de bonnes conditions, en particulier sur un texte aussi technique.

En deuxième lieu, dans votre article vous affirmez que ce projet est précis. Or il y a un point sur lequel il y a un manque de précision, et ce de manière cruciale et que je formulerai sous forme de question : Quels sont les motifs de mise en place d’une surveillance ?

En effet le texte prévoit que les techniques de renseignements pourront être mises en oeuvre pour les motifs suivants:

• « 1° La sécurité nationale ;

• « 2° Les intérêts essentiels de la politique étrangère et l’exécution des engagements européens et internationaux de la France ;

• « 3° Les intérêts économiques et scientifiques essentiels de la France ;

• « 4° La prévention du terrorisme ;

• « 5° La prévention de la reconstitution ou du maintien de groupement dissous en application de l’article L. 212-1 ;

• « 6° La prévention de la criminalité et de la délinquance organisées ;

• « 7° La prévention des violences collectives de nature à porter gravement atteinte à la paix publique.

Si l’on peut être d’accord avec certains motifs, d’autres sont sujets à interrogations.

À titre d’illustration, d’après le point numéro deux, s’engager à l’encontre des engagements européens constituerait un motif valable de mise sous surveillance. Cela concernerait donc votre propre parti lorsque vous appelez à boycotter les élections européennes: http://www.mrc-france.org/Parlement-europeen-cette-election-derisoire-se-fera-sans-nous_a602.html

Concernant le point numéro 3, nous pouvons légitimement nous poser la question de savoir en quoi les intérêts économiques de la France constituent un motif valable de mise sous surveillance. Ainsi, un militant, qui s’opposerait aux intérêts d’une grande multinationale française, pourrait être légalement surveillé.

Le point numéro 7 apparaît beaucoup trop flou, car toutes les manifestations politiques pourraient tomber sous ce motif.

Je n’affirme pas que ce gouvernement met en place une Police politique. Cependant, en manquant cruellement de précision, le législateur laisse aux Gouvernements suivants la possibilité d’utiliser la loi dans leurs propres intérêts. L’affaire des écoutes de l’Élysée démontre que ce risque est réel.

En troisième et dernier lieu, concernant la surveillance généralisée, puisque c’est bien de cela dont il est question, comme vous le soulignez, cela n’est pas efficace. Les fameuses boites noires vont concrètement surveiller tout le trafic sur le réseau pour identifier les comportements suspects.

Affirmer le contraire est soit un mensonge du gouvernement soit un aveu d’inefficacité. Le Gouvernement joue sur les mots en utilisant le terme de “meta données”. En effet, si l’algorithme secret défense du gouvernement ne lira effectivement pas notre email, en revanche, il saura avec qui et quand l’on communique, ainsi que les pages web que l’on consulte. Ce système livre déjà de façon systématique aux autorités des pans entiers de notre vie.

Aussi, je vous invite à ne pas me croire sur parole, mais à vous adresser aux milliers d’étudiants en informatique présents dans votre circonscription.

Par ailleurs, un tel système n’aurait permis d’éviter les évènements tragiques de janvier, où le problème n’était pas les moyens de renseignement disponibles ou le repérage de la menace, mais un manque de moyens humains des services. En outre, les terroristes sont déjà formés à contourner cette surveillance.

Enfin, je ne conteste pas que le citoyen pourra saisir le Conseil d’État en cas de dérive. Mais comment le pourrait-il, car il sera impossible pour lui de savoir que l’on a fait l’objet d’une surveillance particulière qui est par nature secrète ?

Et que risque un agent qui aurait abusé de son pouvoir ? La question demeure sans réponse.

L’impact économique sur votre circonscription est déjà là. L’hébergeur Gandi dont le siège est à 300 mètres d’Ivry à indiquer que dans ces conditions il se développerait à l’étranger. http://fr.gandi.press/100409-loi-sur-le-renseignement-gandi-reste-mobilise

L’année dernière, la ville du Kremlin-Bicêtre accueillait une exposition sur Jean Jaurès. Souvenez-vous de son combat contre les lois scélérates qui furent déjà en leur temps prises pour protéger les citoyens de leurs mauvaises pensées.

Veuillez agréer, Monsieur le Député, l’expression de mes sentiments respectueux.

Julien Duponchelle
123 avenue de fontainebleau
Le Kremlin-Bicêtre

Mise à jours le 25/04/2015: Réponse de Monsieur Jean-Luc Laurent: http://www.jeanluclaurent.fr/Loi-Renseignement-parlons-en_a432.html

Développer pour le Jumping Sumo de Parrot sous Mac

Le Jumping Sumo de Parrot est un petit robot qui roule et peut sauter jusquà 80 cm de haut. Il est aussi équipé d’une Webcam.

Jumping Sumo

Voir sur amazon (lien d’affiliation): Parrot MiniDrone Jumping Sumo Noir

J’en ai reçu un en décembre et après avoir un peu joué avec l’appli android avec j’ai décidé de jouer avec le SDK fournis par Parrot.

Le SDK est en C, ce qui le rend assez facilement portable.

Installation du SDK

Le SDK est disponible sur Github

git clone https://github.com/ARDroneSDK3/ARSDKBuildUtils.git

Ensuite on va le compiler pour MacOS (des version IOS et Android sont disponible aussi, les instructions Mac devrait marcher sous Linux)

./SDK3Build.py -t Unix

Cette commande va télécharger tous les dépots nécessaire au bon fonctionemment du SDK et compiler ce dernier.

Compilation des examples

Faire bouger le jumping sumo

Un deuxième dépot avec des exemples est fournis:

git clone https://github.com/ARDroneSDK3/Samples

Le premier avec lequel on va jouer: Unix/JumpingSumoChangePosture.

On va donc dans le répertoire et on va compiler avec l’aide Make


Puis on se connecte en Wifi du Jumping Sumo Jumping Sumo Wifi

On peut enfin lancer le programme que nous venons de compiler:

# ./JumpingSumoChangePosture
[INF] JumpingSumoChangePosture | 13:16:35:579 | main:134 - -- Jumping Sumo Change Posture --
[INF] JumpingSumoChangePosture | 13:16:35:580 | ardiscoveryConnect:195 - - ARDiscovery Connection
[INF] JumpingSumoChangePosture | 13:16:35:622 | startNetwork:227 - - Start ARNetwork
[INF] JumpingSumoChangePosture | 13:16:35:624 | sendPilotingPosture:341 - - Send Piloting Posture 2
[INF] JumpingSumoChangePosture | 13:16:37:624 | sendPilotingPosture:341 - - Send Piloting Posture 1
[INF] JumpingSumoChangePosture | 13:16:39:626 | stopNetwork:296 - - Stop ARNetwork
[INF] JumpingSumoChangePosture | 13:16:39:643 | main:186 - -- END --

Votre programme devrait localiser automatiquement votre Jumping Sumo sur le Wifi et le faire bouger.

Récupérer la caméra

Un deuxième exemple fournis pour le Jumping Sumo est la récupération du flux de la caméra. Il se trouve dans le répertoire JumpingSumoReceiveStream.

De nouveau vous pouvez le compiler avec make:


Pour afficher le flux il vous faut la commande ffplay ffplay:

brew install ffmpeg --with-ffplay

De nouveau vous pouvez lancer le programme est vous admirer à travers les yeux du Sumo.

Jumping Sumo Camera

Piloter le Jumping Sumo

Le dernier exemple permet de piloter le Jumping Sumo via une interface très minimaliste en curses.

Jumping Sumo Curses

Avec cela combiné vous avez tout ce qu’il vous faut pour jouer sans être olbiger d’utiliser les applis smartphone.

La documentation

Un dépot avec de la documentation existe:

git clone https://github.com/ARDroneSDK3/Docs

Pour la liste des commandes disponibles vous pouvez regarder le fichier ARSDKBuildUtils/Targets/Unix/Install/include/libARCommands/ARCOMMANDS_Types.h


Parrot a fait du bon boulot pour la mise en oeuvre du SDK. A aucun moment je n’ai été bloqué. Et après avoir lu tous les exemples on a tout ce qu’il faut pour créer. Après on regrettera peut être que tous soit balancé sur Github et qu’on ne ressente du coup pas l’envie d’en faire quelque chose de vraiment communautaire (un site dédié à la documentation par exemple serait un plus).

PEP 8 Git pre commit hook

This pre commit hook will check the PEP8 syntax of your Python files and ask you if you want to continue the commit process.

In your project directory create a file: .git/hooks/pre-commit and add the execution permission on it.


echo "Pre-commit started"
echo "PEP 8 check"
git diff  --cached --name-only | grep .py | xargs pep8

if [ $? == 0 ]
    exit 0

# Allows us to read user input below, assigns stdin to keyboard
exec < /dev/tty

echo "Do you want to ignore warning?"
select yn in "Yes" "No"; do
    case $yn in
        Yes ) exit 0;;
        No ) exit 1;;