a3nm's blog

Forkability of community projects

— updated

A community project is an interaction between a community of users who create a resource and a host which stores and serves this resource. Extremely useful and valuable resources such as Wikipedia have been created in this way, and it is easy to feel compelled to contribute to such projects to "give back" to the community. However, in some cases, you could end up benefiting the host more than the community, because the terms of the relationship between community and host are unfair.

Here is an example of this. CDDB was an early collaborative effort to create a database of audio CDs. It started as a one-man effort to which anyone could contribute by email. As time passed, it was incorporated, then bought, then renamed, and access to the database became burdened with restrictions to serve the commercial interests of the host. The users who contributed to the project had actually helped someone to create their product, and that someone ended up using the product against the community's interests.

What went wrong here? Does this mean that the Wikimedia foundation could start to act unethically towards the community? Fortunately not: there is a difference in forkability between Wikipedia and CDDB. I say that a community project is forkable if anyone in the community can take a copy of the content and host it somewhere else. Forkability ensures that the host cannot take the content away from the community. Furthermore, it is a strong guarantee of the optimality of the hosting service, because it ensures that anyone can start to compete with the host.

There are two facets to forkability, which are:

Legal forkability.
Do you have the right to fork? This is satisfied if the resource is under a free license; it is not satisfied if users keep their copyright but grant the current hosting service a right to host the content, or (worse) if they assign their copyright to the host. To publish their content, users should waive the rights that stand in the way, not privilege the current host in any way.
Practical forkability.
Do you have the capacity to fork? This is satisfied if dumps of the resource are provided by the hosting service in an open format (ie. not requiring specific proprietary software); it can still be satisfied if the hosting service allows users to crawl the resource. It is not satisfied if the hosting service tries to prevent crawling or forbids it in their TOS.

Some community projects today are forkable:

Sadly, examples of non-forkable projects today are also numerous:

  • Google Maps welcomes people to contribute, but it is not forkable.
  • Most reviews websites are not forkable. For instance, the Yelp TOS require you to grant them a license to use your content, and prohibits any practical attempts to crawl the content. Reviews on websites such as Amazon are also examples of collaboration to create non-forkable content.
  • ReCAPTCHA is not really a community project but is worth mentioning because you get the same sort of enthusiasm ("awesome! I can help digitize books by completing captchas") before you realize that reCAPTCHA is really Google, that Google never guarantees that you will be able to fork the content that you helped to digitize, and that they are using reCAPTCHA to improve StreetView which is definitely not-forkable.

I don't know of any forkable alternative to Yelp or reCAPTCHA, though I can't see any good reason why such alternatives couldn't exist and thrive (except that they are hard to bootstrap).

So, before you contribute to a community project, make sure that the resource doesn't just belong to the host, but really belongs to the community (and just happens to be hosted in a centralized place). Forkable community projects are, in my opinion, the only ethical alternatives to federated projects; they are a bit worse because they require one master host to exist and because there will always be some degree of inertia before people start to fork, but they are the best that we can do whenever centralization is a technical requirement.

plint -- a French poetry validator

— updated

English version

Version française ci-dessous.

I'm constantly annoyed by French poetry which sort-of rhymes but does not respect metric constraints (and don't get me started on rhyme genres), so I wrote a tool to validate French poetry against metric, rhyme and rhyme genre constraints, which is called plint for lack of a better name.

The code is available so you can run it on your server (or use a CLI or an experimental IRC interface). It uses haspirater as well as a small tool to infer the end phonemes of a word called frhyme (and itself based on Lexique.

Of course, formal constraints are not the only important thing in poetry and you're welcome to deviate from them if you do so willingly. This tool is mostly designed for people who think they're following the rules.

Version française

English version above.

Je suis souvent confronté à de la poésie qui rime plus ou moins mais qui ne respecte aucune contrainte métrique (et ne parlons pas des rimes féminines et masculines), donc j'ai écrit un outil pour vérifier automatiquement les poèmes (pour la métrique, la rime et le genre des rimes). Il s'appelle plint.

Le code est disponible, donc vous pouvez le faire tourner sur votre propre serveur, ou utiliser une interface en ligne de commande ou une interface IRC expérimentale. Il utilise haspirater ainsi qu'un petit outil pour inférer les quelques derniers phonèmes d'un vers qui s'appelle frhyme (utilisant lui-même Lexique).

Bien sûr, la poésie, ce n'est pas que le respect des contraintes formelles, et il peut être raisonnable de s'en écarter à condition de le faire délibérément. Cet outil s'adresse surtout aux gens qui pensent suivre les règles classiques.

RATP, informatique et libertés

— updated

Summary in English

This post isn't of much interest unless you live in France, so I'll write it in French. The gist is that a French law allows you to ask for a copy of the personal data that a company has about you, that I contacted the Paris public transporation agency to request mine, and that I got an actual reply.

L'histoire, en français

Dans les tramways et bus RATP, on peut observer une affiche se terminant par les paragraphes suivants :

Différents sujets évoqués sur cette affiche font l'objet d'un traitement automatisé. (Conformément à la loi 78-17 du 6 janvier 1978 relative à l'informatique, aux fichiers et aux libertés, toute personne peut obtenir communication des données à caractère personnel la concernant et, le cas échéant, exercer son droit de rectification).

Le droit d'accès peut s'exercer auprès du correspondant Informatique et Libertés de la RATP, soit par courrier électronique à cil-ratpNOSPAM@ratp.net, soit par correspondance à l'adresse suivante : RATP - Service de la Direction Générale LAC JV27 - 13, rue Jules Vallès - 75547 Paris

Toute demande doit être accompagnée d'une copie d'une pièce d'identité.

Cette mention légale est fréquente, mais la possibilité d'exercer le droit d'accès par courriel l'est moins. Aussi, curieux de savoir si ça fonctionnait vraiment, j'ai envoyé à tout hasard à l'adresse susmentionnée, le soir du vendredi 27 janvier, le courriel suivant, auquel était joint un scan de mon passeport :

Sujet: Accès aux données à caractère personnel Imagin'R xxxxxxxx

Bonjour,

En application de la loi 78-17 du 6 janvier 1978 relative à l'informatique, aux
fichiers et aux libertés, je souhaiterais exercer mon droit d'accès aux données
à caractère personnel me concernant. En conséquence, je vous prie de me
transmettre une copie de toutes les informations personnelles enregistrées pour
ma carte Imagin'R numéro xxxxxxxx (notamment le relevé des validations
effectuées). Une copie de pièce d'identité est jointe à ce message.

Bien cordialement,

-- 
Antoine Amarilli

J'ai eu la surprise de recevoir, le 30 janvier, une réponse de la RATP :

Pour répondre à votre demande, je vous transmets ci-joints :

- la fiche client des informations de votre passe NAVIGO et du contrat Imagine'R
étudiant qui lui est associé

- le cumul des validations de ce passe effectuées en entrée ou en sortie de
nos réseaux ferrés au cours de ce mois (Janvier 2012)  et du mois précédent
(Décembre 2011). Les données de cumul journalier sont conservées pendant ce
maximum de 2 mois à seule fin de vérification de la fiabilité des passes NAVIGO.
Nous ne conservons ni les heures ni les lieux de passage.

Le cumul des validations est un document PDF créé à partir de Microsoft Word. Il se borne effectivement à une indication du nombre de passages pour les dates des mois de décembre et janvier. La fiche client est un document PDF un peu plus intéressant contenant toutes sortes d'informations dont :

  • Le code Hexaclé de l'adresse postale indiquée par le client. Je ne connaissais même pas l'existence de ce code, mais il semble assez difficile d'obtenir le sien par ailleurs vu que la base de données Hexaclé n'est pas gratuite...
  • Des indications de si vous acceptez ou non la pub : "Opt-in source", "Opt-in console", "Stop pub source" et "Stop pub console", ainsi que de plus énigmatiques "Demande de non regroupement" et "Déduplication à tort".
  • Toutes sortes d'information sur vos passes : numéro de lot, numéro de version, etc.
  • Des événements concernant le rechargement de passes Navigo. L'historique remonte assez loin, mais je n'en vois qu'un par passe, donc il doit en manquer et il se pourrait que ce soit juste la création des passes.

Je reste assez surpris d'avoir effectivement obtenu ces données de la RATP. Quelques remarques en conclusion :

Peu d'informations.
La RATP ne garde (ou ne prétend garder) que peu d'informations. J'espérais obtenir le relevé des dates, heures et lieux de validation du passe Navigo sur une durée arbitrairement longue. À moins qu'on m'ait menti, je suis assez agréablement surpris de voir que la RATP prend effectivement la peine d'effacer les informations.
Exploitation régulière
Évidemment, plutôt qu'une communication ponctuelle, je préférerais que la RATP m'envoie ces informations au fur et à mesure qu'elles se construisent (pour conserver la liste de toutes mes validations de Navigo), et si possible dans un format facile à traiter (CSV, SQL...). J'ai répondu à leur message pour les interroger à ce sujet et on m'a répondu que le format PDF satisfaisait les obligations de la loi 78-17, qu'il n'était pas prévu de transmettre de manière régulière ces données, et qu'une demande tous les deux mois pourrait être considérée comme abusive du fait de son caractère répétitif (ce qui est effectivement conforme à la loi en question, article 39, paragraphe II).
Sécurité
L'authentification des demandes par la RATP s'appuie exclusivement sur la fourniture d'une copie de pièce d'identité. Il y a là confusion entre l'identification d'une personne (désigner un individu de façon non-ambiguë) et l'authentification d'une demande (garantir que c'est bien la personne concernée qui effectue la demande). Une copie de pièce d'identité, si elle n'est pas falsifiée, permet d'identifier la personne, mais ne certifie pas qu'elle a autorisé la demande : certaines personnes tierces disposent d'un scan de mon passeport et pourraient obtenir de la RATP mes informations personnelles (incluant le numéro de téléphone, l'adresse, et des informations agrégées donnant cependant une idée de ma présence ou non en région parisienne...) en se faisant passer pour moi. À mon avis, il serait déjà préférable que la RATP vérifie qu'elle transmet bien les informations à l'adresse de courriel indiquée sur la fiche client (ce qui n'a pas été fait dans mon cas, puisque j'ai effectué la demande depuis une autre adresse). J'ai adressé ces suggestions à la RATP, qui n'y a pas apporté de réponse.

htmlrebase -- relative link resolution in HTML according to a given base URL

— updated

I found this code lying around, so I'm dumping it here in case someone needs it. It takes an HTML file on standard input and a URL as a command-line argument and produces the HTML file on standard output where all relative links have been resolved according to the given base URL.

#!/usr/bin/env python

"""Resolve relative links in an HTML blob according to a base"""

from BeautifulSoup import BeautifulSoup
import sys
import urlparse

# source: http://stackoverflow.com/q/2725156/414272
# TODO: "These aren't necessarily simple URLs ..."
targets = [
    ('a', 'href'), ('applet', 'codebase'), ('area', 'href'), ('base', 'href'),
    ('blockquote', 'cite'), ('body', 'background'), ('del', 'cite'),
    ('form', 'action'), ('frame', 'longdesc'), ('frame', 'src'),
    ('head', 'profile'), ('iframe', 'longdesc'), ('iframe', 'src'),
    ('img', 'longdesc'), ('img', 'src'), ('img', 'usemap'), ('input', 'src'),
    ('input', 'usemap'), ('ins', 'cite'), ('link', 'href'),
    ('object', 'classid'), ('object', 'codebase'), ('object', 'data'),
    ('object', 'usemap'), ('q', 'cite'), ('script', 'src'), ('audio', 'src'),
    ('button', 'formaction'), ('command', 'icon'), ('embed', 'src'),
    ('html', 'manifest'), ('input', 'formaction'), ('source', 'src'),
    ('video', 'poster'), ('video', 'src'),
]

def rebase_one(base, url):
    """Rebase one url according to base"""

    parsed = urlparse.urlparse(url)
    if parsed.scheme == parsed.netloc == '':
        return urlparse.urljoin(base, url)
    else:
        return url

def rebase(base, data):
    """Rebase the HTML blob data according to base"""

    soup = BeautifulSoup(data)

    for (tag, attr) in targets:
        for link in soup.findAll(tag):
            try:
                url = link[attr]
            except KeyError:
                pass
            else:
                link[attr] = rebase_one(base, url)
    return unicode(soup)


if __name__ == '__main__':
    try:
        base = sys.argv[1]
    except IndexError:
        print >> sys.stderr, "Usage: %s BASEURL" % sys.argv[0]
        sys.exit(1)

    data = sys.stdin.read()
    print rebase(base, data)

Ambiguous verbal forms in French

— updated

This list is incomplete! You should see the new list instead! Cette liste est incomplète! Regardez plutôt la nouvelle liste!

English explanations

Added "méprise" and "méprises", thanks to Erik McDonald.

In this post, I present a list of French verbal forms which are ambiguous because they can be derived from different infinitives (always two). To determine which are those derivations (infinitive, mode, tense, person), you can use french-deconjugator from Verbiste. This (hopefully complete) list has been computed using Lexique. See also my list of non-homophonous homographs in French and my list of French words without rhymes.

Explications en français

Ajout de "méprise" et "méprises", merci à Erik McDonald.

Ce post présente une liste de formes verbales du français qui sont ambiguës car elles peuvent être dérivées de plusieurs infinitifs différents (toujours exactement deux). Pour déterminer quelles sont les dérivations possibles (infinitif, mode, temps, personne), vous pouvez utiliser french-deconjugator de Verbiste. Cette liste que j'espère exhaustive a été calculée avec Lexique. Voir aussi ma liste d'homographes non-homophones en français (en anglais) et ma liste de mots français sans rimes.

The list / la liste