Christophe Nowicki

August 1, 2009

Laconica, un twitter libre!

Pour ceux qui me côtoient tous les jours, j’ai principalement deux gros défauts:

  • Je m’intéresse à trop de choses … ;-)
  • J’envoie de la “propagande” par Jabber à mes contacts.

Du coup, le principe du Micro-blogging et du service Twitter m’a beaucoup séduit.

Mais comme je suis un Ayatollah du logiciel libre et que je prône l’auto-hébergement.
Mon inscription sur un service web deux points zéro centralisé aurait fait un peu tâche dans ma pratique du logiciel libre radical (vu le nombre de mots clés dans cette phrase, je pense que je vais avoir droit à une décente des RG ;-) ).

Je viens de trouver la solution, Laconica (prononcé “luh-KAWN-ih-kuh”), un logiciel de micro-blogging libre écrit en PHP. L’objet de cet article est de décrire l’installation, la configuration et la mise en place de passerelles (mail, twitter, sms, et jabber) sur un serveur Debian GNU/Linux.

Les Fonctionnalités

Le logiciel dispose des fonctionnalités suivantes :

  • Micro-blogging ;
  • Export des données au format RSS / Atom ;
  • Authentification via OpenID ;
  • Gestion de plusieurs comptes ;
  • Interface Jabber : notification et post ;
  • Interface avec Twitter ;
  • Notification via SMS ;
  • Feuille de style pour les mobiles ;
  • Une traduction de qualité en Français ;
  • Gestion du format FOAF ;
  • Intégration avec de nombreuses application ;
  • Affichage des messages via un “badge” directement dans le code de votre site web : Identica Badge ;
  • Génération automatique de Sitemaps pour le référencement ;
  • Support du protocole OpenMicroBlogging pour le suivi décentralisé des messages.

Pré-requis

Pour l’installation de Laconica vous avez besoin :

  • d’un serveur sous Debian GNU/Linux ;
  • serveur HTTP comme Apache 2 ;
  • base de donné comme MySQL ou bien Postgresql ;
  • d’un serveur de Mail ;
  • d’un serveur Jabber (optionnel) ;

Installation des dépendances

Le programme nécessite les dépendances suivantes :

# apt-get install apache2-mpm-prefork libapache2-mod-php5 php5-mysql php5-gd php5-cli php-pear php-mail php-db php-http php-xml-parser php5-curl

Installation du logiciel

Laconica, est une application web, l’installation consiste simplement à extraire le fichier tgz dans le répertoire /var/www et configurer Apache.

# cd /var/www
# wget http://laconi.ca/laconica-0.8.0.tar.gz
# tar xvf laconica-0.8.0.tar.gz
# ln -s laconica-0.8.0 laconica
# chown www-data: laconica-0.8.0
# cd laconica
# mv htaccess.sample .htaccess

Il faut éditer le fichier .htaccess pour modifier la règle RewriteBase.

Vous devez ensuite configurer le site web pour Apache en mettant le contenu suivant dans le fichier /etc/apache2/sites-available/laconica :

<virtualhost *:80>
ServerName mblog.nom_de_domaine
ErrorLog /var/log/apache2/mblog.nom_de_domaine/error.log
CustomLog /var/log/apache2/mblog.nom_de_domaine/access.log common
DocumentRoot /var/www/laconica
</virtualhost>

Il faut créer le répertoire pour les logs du site, activer le site et le module rewrite dans Apache :


# mkdir /var/log/apache2/mblog.nom_de_domaine/
# a2enmod rewrite
Enabling module rewrite.
Run '/etc/init.d/apache2 restart' to activate new configuration!
# a2ensite laconica
Enabling site laconica.
Run '/etc/init.d/apache2 reload' to activate new configuration!
# /etc/init.d/apache2 restart

Vous devez créer une base de données avec MySQL ou PostgreSQL et attribuer tous les droits sur la base à un utilisateur.

Vous pouvez ensuite pointer votre navigateur sur l’adresse de votre site : http://mblog.nom_de_domaine/install.php

La procédure d’installation vous demande simplement les informations de connexion à la base de données.

Une fois l’installation effectuée, vous pouvez vous enregistrer et utiliser l’application.

Configuration Mono-utilisateurs

Une fois que vous avez créer votre compte et que vous êtes le seul à utiliser l’application; il faut interdire les enregistrements de nouveau compte en modifiant le fichier config.php :
$config['site']['closed'] = true;

Configuration de la passerelle Twitter

Mouahah, et puis quoi encore? Non, je n’ai pas testé, je n’ai pas réussi à créer un compte …
Mais d’après la documentation de Laconica, il suffit de saisir son login et mot de passe.

Configuration de la passerelle de Messagerie

Pour cette partie, il faut créer un alias spécial sur votre serveur de messagerie.
Voici ma configuration pour Postfix.
Dans le fichier /etc/aliases, il faut ajouter la ligne suivante :
*:|/var/www/laconica/scripts/maildaemon.php
Refaire la base des alias de postfix :
# postalias /etc/aliases
Rendre le fichier maildaemon.php exécutable.
chmod +x /var/www/laconica/scripts/maildaemon.php
Ce script pour fonctionner nécessite l’extension PECL mailparse de PHP.
La procédure d’installation est la suivante :
# apt-get install dh-make-php php5-dev xsltproc
# cd /usr/src/
# dh-make-pecl --only 5 mailparse
downloading mailparse-2.1.5.tgz ... Starting to download mailparse-2.1.5.tgz (37,332 bytes) ..........done: 37,332 bytes File /var/www/laconica/scripts/mailparse-2.1.5.tgz downloaded
Creating debian source package: php-mailparse-2.1.5
Upstream is: Wez Furlong, Brian Shire
Guessing Maintainer: root
# cd php-mailparse-*/
# dpkg-buildpackage -b
...
# dpkg -i ../php5-mailparse_2.1.5-1_i386.deb

Une fois la passerelle en place, il faut créer une adresse “incoming” :
Pour cela, il faut aller dans la configuration e-mail de votre compte et cliquer sur nouveau pour obtenir une adresse de type : XMWY7QTL3MR42@votre_nom_de_domaine.

Vous pouvez ensuite envoyer un mail à cette adresse et vérifier que tout ce passe bien dans les logs de postfix :

Jul 31 11:02:50 mail postfix/local[30821]: E76C8F40FB: to=<XMWY7QTL3MR42@csquad.org>, relay=local, delay=0.56, delays=0.01/0/0/0.55, dsn=2.0.0, status=sent (delivered to command: /var/www/laconica/scripts/maildaemon.php)

Une petite astuce pour une installation perso, est de faire un seul alias et de modifier le contenu de la table user.incomingemail dans la base de données.

Configuration de la passerelle Jabber

Il faut modifier le fichier de configuration config.php et ajouter les lignes suivantes :

$config['xmpp']['enabled'] = true;
$config['xmpp']['server'] = "jabber.csquad.lan";
$config['xmpp']['port'] = 5222;
$config['xmpp']['user'] = "laconica";
$config['xmpp']['password'] = "***********";
$config['xmpp']['encryption'] = true;
$config['daemon']['user'] = "www-data";
$config['daemon']['group'] = "www-data";

Laconica, ne sait pas s’enregistrer auprès du serveur, ni s’ajouter dans votre roaster, il faut donc le faire manuellement,
soit à l’aide d’un client Jabber classique ou bien à l’aide de l’interface d’administration de votre serveur.
Ejabberd permet de le faire directement via l’interface Web.

Vous pouvez ensuite lancer le daemon à l’aide de php en ligne de commande :

# cd /var/www/laconica/
# php scripts/xmppdaemon.php -f
2009-07-31 06:59:42 LOG_INFO: XMPPDaemon(uniquenamedaemon): INITIALIZE XMPPDaemon laconica@jabber.csquad.lan/uniquenamedaemon
2009-07-31 06:59:42 LOG_INFO: XMPPDaemon(uniquenamedaemon): Connecting to jabber.csquad.lan on port 5222
2009-07-31 06:59:42 LOG_INFO: XMPPDaemon(uniquenamedaemon): Connected
2009-07-31 06:59:42 LOG_INFO: XMPPDaemon(uniquenamedaemon): Sending initial presence.
2009-07-31 06:59:42 LOG_INFO: XMPPDaemon(uniquenamedaemon): Done connecting.
2009-07-31 06:59:42 LOG_DEBUG: XMPPDaemon(uniquenamedaemon): Initializing stanza handlers.
2009-07-31 06:59:42 LOG_DEBUG: XMPPDaemon(uniquenamedaemon): Beginning processing loop.

Une fois lancé, le contact du micro blog doit apparaître dans votre client Jabber.
Mais lorsque vous lui parlez, il ne vous reconnait pas. Il faut donc associé le compte Jabber à votre compte Laconica.
Pour cela, rendez-vous sur l’interface de configuration à l’adresse suivante : http://mblog.votre_nom_de_domaine/settings/im,
et saisissez votre adresse Jabber que Laconica vous demandera de confirmer à l’aide d’une url de vérification.

Et voila, tous les messages que vous envoyez à ce contact Jabber se retrouvent directement sur votre micro blog ;-)
Et lorsqu’un utilisateur poste un message vous recevez celui-ci sur votre compte Jabber.

Suivre une personne de manière distribuée

Pour suivre une personne sur Laconica de manière distribuée, il suffit de cliquer sur le bouton subscribe du profil.
L’application vous demande, le pseudo de la personne et l’url de votre profil.
Celle-ci est de la forme : http://laconica.<votre_domaine>/<nickname>/.

Conclusion

Et voilà ! Laconica ça poutre les ours ! ;-)

Filed under: Debian,Network — Tags:, , , , , — cscm @ 14:00

June 11, 2009

Héberger son propre fournisseur d’identité OpenID

Présentation d’OpenID

OpenID est un système d’authentification décentralisé qui permet l’authentification unique, ainsi que le partage d’attributs. Il permet à un utilisateur de s’authentifier auprès de plusieurs sites compatibles sans avoir à retenir un identifiant pour chacun d’eux mais en utilisant à chaque fois un unique identifiant OpenID.

Cette identifiant se presente sous forme d’URL, celle-ci contient l’adresse du serveur d’identification et le nom de l’utilisateur : http://id.csquad.org/identity/cscm

Je trouve ce système d’identification pratique, car je change de poste de travail ( portable, station de travail, etc…) et je n’ai pas trouvé de solution de synchronisation de mot de passe convaincante.

Pourquoi héberger son propre fournisseur d’identité?

Héberger son propre serveur d’identité vous permet de gérer votre identité numérique.
C’est à dire, déterminer les informations personnelles que vous fournissez au service que vous utilisez.
Héberger ce type de service sur son propre serveur vous garantit que vous avez la main sur vos données personnelles.
Cela vous garantit que :

  • les autres fournisseurs d’identité n’exploitent pas vos données personnelles ;
  • votre compte restera toujours actif, en effet rien ne vous garantit qu’un fournisseur d’identité ne cesse son activité ;
  • une liberté en matière de politique de mot de passe / choix de l’identifiant / nombre de comptes, etc…

Présentation de Community-ID

Community-ID est une application PHP, compatible avec les spécifications OpenID 2.0 sous licence BSD.
Il propose les fonctionnalités suivantes :

  • comptes d’utilisateurs ;
  • données personnelles ;
  • sites fédérés ;
  • historique ;

Configuration de Community-ID sur un serveur Debian GNU/Linux

Voici la procédure d’installation de la version 1.0 de Community-ID sur une distribution Debian GNU/Linux version “Lenny”.

Vous avez besoin :

  • d’un nom de domaine ;
  • d’un serveur Apache avec le support de PHP 5 et le module rewrite ;
  • d’une base de données MySQL avec phpMyAdmin ;

Configuration de MySQL

A l’aide de phpMyAdmin, créer un utilisateur communityid et créer une base portant le même nom en lui donnant tous les privilèges sur cette base.

Installation dépendances

Le programme nécessite les dépendances suivantes :

# apt-get install apache2-mpm-prefork libapache2-mod-php5 php5-mysql php5-gd php5-gmp

Installation du programme

Vous pouvez télécharger le programme sur SourceForge : Community-ID.
et extraire le fichier tar.gz dans le répertoire /var/www :


# cd /var/www
# wget http://freefr.dl.sourceforge.net/sourceforge/communityid/cid-1.0.0.tar.gz
# tar xzf cid-1.0.0.tar.gz
# chown www-data: -R communityid

Vous devez ensuite configurer le site web pour Apache en mettant le contenu suivant dans le fichier /etc/apache2/sites-available/communityid :


<VirtualHost *:80>
ServerName id.nom_de_domaine
ErrorLog /var/log/apache2/id.nom_de_domaine/error.log
CustomLog /var/log/apache2/id.nom_de_domaine/access.log common
DocumentRoot /var/www/communityid/webdir
</VirtualHost>

Il faut créer le répertoire pour les logs du site, activer le site et le module rewrite dans Apache :

# mkdir /var/log/apache2/id.nom_de_domaine/
# a2enmod rewrite
Enabling module rewrite.
Run '/etc/init.d/apache2 restart' to activate new configuration!
# a2ensite communityid
Enabling site communityid.
Run '/etc/init.d/apache2 reload' to activate new configuration!
# /etc/init.d/apache2 restart

Configuration

Vous pouvez ensuite pointer votre navigateur sur l’adresse de votre site : http://id.nom_de_domaine/
La procédure d’installation vous demande les informations de connexion à la base de données pour configurer celle-ci.
Une fois la base de données crée, vous pouvez vous connecter à l’interface à l’aide de l’utilisateur admin et du mot de passe admin, pour vous créer un compte.

Liste des services compatibles

Voici la liste des quelques services que j’utilise avec mon serveur OpenID :

Il existe de nombreux services compatibles avec ce système d’authentification, référencés par l’annuaire OpenID Directory.

Les principaux systèmes de blog proposent le support d’OpenID sous forme de plugin :

Si vous avez réussi à installer votre fournisseur d’identité, vous pouvez vous connecter sur mon blog pour me laisser un commentaire ;-)

Filed under: Debian — Tags:, — cscm @ 07:31

February 4, 2009

Retour sur l’optimisation des performances du projet MAVISE

La base de données MAVISE fournir les données de base sur l’ensemble des chaînes de télévision accessibles dans l’Union européenne.
Elle à été développer par la société Easter-eggs pour le compte de la DG Communication de la Commission européenne.
Je vais décrire dans cet article les diffèrentes méthodes que nous avons mise en place pour optimiser les performances de cette application.

Problèmatique

La base de données contiens beaucoups d’informations :

  • la description du paysage audiovisuele de 30 pays ;
  • des fiches sur 5000 chaînes de télévision ;
  • des fiches sur 4000 entreprises ;
  • des fiches sur 8000 programmes de télévision ;

L’ensemble des ses données ne sont pas accessibles au grand publique.

D’un point de vu technique, la base de données PostgreSQL contient :

  • 115 tables ;
  • 100 vues ;
  • 220Mo de données.

Cela vous donne une petite idées de la taille de l’application.
La complexitées de l’application, la quantité de données disponibles et leur affichage nous as posées de nombreux problèmes :

  • Quantité de données très importante à transferer entre le client et le serveur Web ;
  • Requêtes complexes au niveau de la base de données ;

Optimisation de la base de données

Pour l’optimisation de la base de données, il faut faire attention aux points suivants :

  1. L’ORM (DB_DataObject dans notre cas) ne doit faire aucune opération de jointure . Il utilise toujours une vue dédier pour chaque fonctionnalitées ;
  2. Chaque vue ne calcule que les champs qui sont nécessaire à l’affichage ;
  3. Le plan d’execution de chaque vue est optimiser à l’aide d’index. Pour trouver quels sont les indexes à créer, il faut utiliser l’instruction EXPLAIN ANALYSE , comme décrit sur le wiki de Postgres : Using EXPLAIN.

Le travail principal consiste donc à éxécuter toutes les vues de l’application pour optimiser les plans d’éxécution à l’aide d’indexes.
Pour mieux comprendre la sortie de l’instruction EXPLAIN ANALYSE, j’utilise l’outil suivant : explain-analyze.info.

Pour savoir quelles sont les optimisations les plus pertinantes, il est intéressant d’analyser les logs du serveur Postgres à l’aide du logiciel Practical Query Analysis.

Il faut aussi “tuner” la configuration du serveur de base de données pour utiliser le maximum de la mémoire disponible sur le serveur.

Javascript

Nous avons utilisé le framework Javascript Mootools, le contrôleur de tableau dhtmlxGrid et l’éditeur de contenu TinyMCE.

Dans chaque page de l’application, il faut faire attention à ne charger que les fichiers nécessaire.
En effet, ces outils, bien que très pratiques sont très volumineux et augementent la taille des pages dans des proportions importantes.

Dans certains cas, nous avons dépasser plus de 640Ko de code Javascript dans une page ;-)

Les solutions que nous avons mis en place pour réduire la taille de ces fichiers :

  • La compression Gzip, malheureusement nous avons rencontrer de problèmes très importants avec Internet Explorer ;
  • Nous avons ensuite opter pour YUI Compressor qui fonctionne bien mieux ;

Systèmes de Cache

L’application dispose de nombreux systèmes de caches :

  • Le système de cache du gestionaire de template Smarty ;
  • Notre propre système de cache pour le contenu des tableaux, réalisé à l’aide du module Pear Cache_Lite ;
  • L’API de XCache, pour certains calculs et XCache pour les opcodes PHP ;
  • Le système de cache d’Apache Cocoon pour le système d’impression ;
  • La cache du navigateur des utilisateurs. Il est possible de bien contrôler le contenu du navigateur des clients à l’aide du module mod_expires d’Apache.

Réduction de la taille des pages

Nous avons travailler pour réduire au maximum la taille des échanges entre le navigateur web et le serveur.
Pour cela nous avons utilisé la compression Gzip sur :

  • Le contenu des tableaux ;
  • Les pages produites par le système de tempate ;

Celle-ci est réalisé par le gestionnaire de tempon de PHP, à l’aide de la fonction ob_gzhandler ;

Outils utilisés

L’optimisation d’une application est toujours empirique, il est nécessaire d’avoir de bon outils pour observer les effets des modifications.
Pour cela nous avons utilisé :

Les liens utiles pour l’optimisation des performances d’une application Web

Pour finir, voici quelques liens très interessants sur l’optimisation d’une application Web :

Filed under: Programming,Work — Tags:, , — cscm @ 21:42

June 3, 2008

Validation d’un fichier CSV à l’aide d’un Schéma XML

Malgré tout le mal qu’il est possible de penser ou de dire sur le format de fichier CSV, celui-ci présente beaucoup d’avantages :

  • il est facilement manipulable pour les utilisateurs à l’aide d’un tableur comme Calc, Gnumeric ou bien Excel ;
  • il permet d’écrire rapidement et facilement des routines d’import / export ;
  • il permet d’échanger les données entre des bases et des systèmes hétérogène.

Mais ce format de fichier ne dispose pas d’un système de validation. Dans la plupart des cas ce sont les routines d’import / export qui prennent en charge la validation des données et de leur mise en forme.

Ce travail est pénible, répetitif et ennuyeux mais nécessaire si vous ne voulez pas qu’un fichier mal formaté ne corrompe les données de votre base.

L’objectif de cette article est de proposer une solution simple permettant la validation d’un fichier CSV en utilisant les fonctionnalités offertes par les schémas XML.

Les exemples fournis sont écrit à l’aide du language de programmation PHP5.

Transformation CSV vers XML

Votre fichier doit contenir sur la 1ère ligne, le nom de chaque cologne :

“CHANNEL”;”COMPANY”;”BVD_ID_Groupe_1″;”BVD_ID_Groupe_2″;”GENRE”;”URL”;”OTHER_URL”;”COMPETENT_AUTHORITY”
“Canal+ Film 1″;”C MORE ENTERTAINMENT AB”;”NL33268595″;”DE8330261794″;”CIN”;”http://www.canalplus.se”;”http://www.sbsbroadcasting.com/, http://www.prosiebensat1.de/”;”RTVV”
“Canal+ Film 2″;”C MORE ENTERTAINMENT AB”;”NL33268595″;”DE8330261794″;”CIN”;”http://www.canalplus.se”;”http://www.sbsbroadcasting.com/, http://www.prosiebensat1.de/”;”RTVV”
“Canal+ Film 2 Sport Weekend”;”C MORE ENTERTAINMENT AB”;”NL33268595″;”DE8330261794″;”CIN”;”http://www.canalplus.se”;”http://www.sbsbroadcasting.com/, http://www.prosiebensat1.de/”;”RTVV”
“Canal+ Film 3″;”C MORE ENTERTAINMENT AB”;”NL33268595″;”DE8330261794″;”CIN”;”http://www.canalplus.se”;”http://www.sbsbroadcasting.com/, http://www.prosiebensat1.de/”;”RTVV”
“Canal+ Film HD”;”C MORE ENTERTAINMENT AB”;”NL33268595″;”DE8330261794″;”CIN”;”http://www.canalplus.se”;”http://www.sbsbroadcasting.com/, http://www.prosiebensat1.de/”;”RTVV”

Pour transformer le fichier CSV en XML, il suffit de lire le fichier CSV avec la fonction fgetcsv et mettre les données dans des balisent XML : csv_to_xml.php

Une fichier CSV converti en XML ressemble à cela : channel.xml

Validation du fichier XML

Il ne reste plus qu’à écrire le schéma permettant de valider le fichier XML : channel.xsd

Vous pouvez tester vos schéma en ligne de commande en utilisant la commande xmllint issue du paquet Debian libxml2-utils :


$ xmllint --noout --schema channel.xsd channel.xml
channel.xml validates

Validation en PHP

Une fois que votre schéma est correct et permet de valider le contenu du fichier XML, il faut l’intégrer directement dans votre application : validate.php

Conculsion

Cette méthode apporte les avantages suivants :

  • Les règles de validation sont décrites directement via le schéma, et celui-ci dispose de nombreuses fonctionnalités tels les types de bases, les expression rationnelle, les séquences, etc…
  • Les messages d’erreur sont compréhensibles pour l’utilisateur même, s’il faut parfois les traduire (en convertissant les numéros de lignes et certaines notions) ;
  • La simplicité ;0)

Cette technique a été mise en oeuvre dans le cadre du projet MAVISE pour valider plus d’une vingtaine de formats de fichiers différents.

Filed under: Work — Tags:, , , — cscm @ 07:10

May 30, 2008

Système de synchronisation conditionnel pour PostgreSQL

Il existe des outils tel que SQLSync permettant de synchroniser les données d’une base PostgreSQL. Mais cette outil, ne permet pas de faire une copie partiel des données.
Dans la plus part des cas, il faut programmer la synchronisation soit même, l’objectif de mon article est de vous proposer une solution simple et élégante.

La problèmatique

Des données sensibles se trouvent dans la base principale et il ne faut synchoniser qu’une partie de ces données vers les autres bases.

L’architecture dispose des caractèristiques suivantes :

  • Le schèma est identique sur chaque base ;
  • Les opèrations d’écriture se font seulement sur la base principale ;
  • Les bases sont accessibles en réseau.

La solution

Pour résoudre le problème, j’ai testé plusieurs approches avant de retenir l’utilisation d’un fonction de hachage dont voici le principe :

  • chaque table doit disposer d’un identifiant unique. (champ id de type SERIAL) ;
  • un programme récupère le couple id et la sum de hachage pour chaque table de chaque base qui doit être synchroniseés ;
  • il compare le couple et si celui-ci est diffèrent alors les données sont mise à jour.

Implementation au niveau de la base de données

Le calcul de la somme de hachage se fait un niveau de la base de données à l’aide d’un fonction :

SELECT id,md5 FROM get_table_md5('nom_de_la_table');
 id |               md5
----+----------------------------------
  4 | 9f3bcd2fae528244669613ae0466cc3c
  5 | 1f3bcd2fa24528244669613ae66cc3czd
...
(42 row)

Voici le code de la function PL/Perl:

CREATE LANGUAGE plperl;
CREATE TYPE table_md5 AS (id INTEGER, md5 TEXT);
CREATE OR REPLACE FUNCTION get_table_md5(varchar) RETURNS SETOF table_md5 AS $$
    my ($rv, $status, $nrows, $row);
    # Get Table OID
    $rv = spi_exec_query("SELECT c.oid AS oid FROM pg_catalog.pg_class c
        LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
        WHERE c.relname LIKE '$_[0]';");
    $status = $rv->{status};
    $nrows = $rv->{processed};
    return undef if ($nrows != 1);
    my $oid = $rv->{rows}[0]->{oid};
    # Get Table attributs
    $rv = spi_exec_query("SELECT attname,atttypid FROM pg_catalog.pg_attribute a
        WHERE a.attrelid = $oid AND a.attnum > 0 AND NOT a.attisdropped");
    $status = $rv->{status};
    $nrows = $rv->{processed};
    return undef if ($nrows < 1);
    my $atts;
    my $atts_not_null;
    foreach my $rn (0 .. $nrows - 1) {
        if ($rv->{rows}[$rn]->{atttypid} == 16) {
            $atts .= " (CASE WHEN $rv->{rows}[$rn]->{attname} THEN 't' ELSE 'f' END) AS $rv->{rows}[$rn]->{attname}";
        } else { 
            $atts .= " $rv->{rows}[$rn]->{attname}::text";
        }
        $atts_not_null .= " (CASE WHEN $rv->{rows}[$rn]->{attname} IS NULL THEN '' ELSE $rv->{rows}[$rn]->{attname} END)";
        $atts .= ',' if ($rn != $nrows - 1);
        $atts_not_null .= ' || ' if ($rn != $nrows - 1);
    }
    # Calc MD5
    my $sql = "SELECT id, MD5($atts_not_null) AS md5 FROM (SELECT $atts FROM $_[0]) AS $_[0];";
    $rv = spi_exec_query($sql);
    $nrows = $rv->{processed};
    foreach my $rn (0 .. $nrows - 1) {
        return_next({
            id  => $rv->{rows}[$rn]->{id},
            md5 => $rv->{rows}[$rn]->{md5}
        });
    }
    return undef;
$$ LANGUAGE plperl;

Pour utiliser cette fonction vous avez besoin du support du language de programmation PL/Perl dans Postgres, celui-ci se trouve dans le paquet Debian : postgresql-plperl-

La gestion des conditions

Le choix des données à synchroniser se fait individuellement pour chaque table à l’aide de la clause WHERE de la manère suivante :

SELECT id,md5 FROM get_table_md5('nom_de_la_table') WHERE id IN(SELECT id FROM nom_de_la_table WHERE nom_de_la_table.champ LIKE 'sync');
 id |               md5
----+----------------------------------
  1 | fdd56eabd4bb997e453e33f0022d46c1
(1 row)

Implementation du script de synchronisation

La synchronisation des données peut être réalisée à l’aide de n’importe quel language de programmation,
il suffit juste de disposer d’un accèss à la base de données.

Voici un exemple de script écrit par Emmanuel Saracco en PHP5 qui se repose sur les modules PEAR suivants :

  • DB : pour l’accès à la base de donnée.
  • Console_Getopt : pour la gestion de la ligne de commande.

Ce script nécessite un fichier de configuration, en voici un exemple.
Ce fichier contiens la configuration des diffèrentes base de données et les conditions sous-forme de clauses where.

Conclusion

Cette méthode de synchronisation fonctionne, elle est en production chez un client pour une base de données de plus de 100 tables, elle permet de synchronisé le contenu d’une base vers deux autres.
Les avantages de cette méthode sont les suivants :

  • le fait de pouvoir choisir le contenu de la clause where permet de réalisé des régles de synchronisation très complexes ;
  • les performances sont très bonnes car les transfert réseau sont limités ;
  • il est possible d’écrire le script de synchronisation avec n’importe quel language de programmation.
Filed under: Work — Tags:, , — cscm @ 14:30

June 1, 2006

PHP REST SQL, Web Services for dummies

Je vous passe l’ensemble de la propagande habituelle sur les Web Services ( l’architecture SOA, Annuaires de services, SOAP, etc…).

Pour ma part, je pense qu’il existe deux grandes familles de WebServices :

  • Contrôle : l’éxécution d’action
  • Données : la mise à disposition d’informations

Pour la première famille, l’ensemble des techniques disponibles (SOAP, WSDL, UDDI) couvrent les besoins.
Quant à la seconde famille, je trouve que ces techniques sont bien trop complexes à mettre en oeuvre.

Problèmatique

Imaginons que vous avez besoin de mettre à disposition le contenu d’une base de données relationnelles ( liste de contacts, tickets, commandes en cours, etc. ) à l’aide d’un Service Web.

1/ Solution envisagée : le développement d’une Interface SOAP spécifique à votre problèmatique

Le développement de celle-ci sera long, car il vous faudra :

  • désigner l’interface
  • développer les composants
  • tester le fonctionnement
  • écrire la documentation

2/ Solution envisagée : adopter la méthodologie REST

J’ai découvert cette méthodologie suite à un article du journal du Net : SOAP, XML-RPC et EST : différences et intérêts

Elle est spécifiée dans le mémoire de Roy Thomas Fielding : Architectural Styles and the Design of Network-based Software Architectures

Ce qui est remarquable dans cette méthodologie, c’est :

  • sa simplicité
  • la réutilisation de protocoles standards éxistants du web
  • la possiblité de mettre en cache le résultat de la requête de manière transparente.

Le project PHP REST SQL

Par la suite, j’ai découvert le projet PHP REST SQL, celui-ci permet de mettre à disposition le contenu d’une base de données MySQL via une interface Web.

Ce projet consiste en une classe, qui s’interface avec une base de données MySQL et qui permet à l’aide de requêtes HTTP de récupèrer les données de la base, créer, modifier et supprimer des champs.

Ma contribution : abstraction par rapport aux bases de données

Actuellement, le projet ne supporte que les bases de type MySQL, j’ai donc réécrit la classe pour prendre en comptes toutes les bases de données supportées par le module PEAR MDB ( MySQL, PostGreSQL, Oracle, Frontbase, Querysim, Interbase/Firebird, MSSQL et SQLite).

J’ai testé son fonctionnement avec 3 bases (MySQL, PostGreSQL et SQLite).

Cette contribution est disponible sur SourceForge : database abstraction (MySQL, Postgres and SQLite Support).

Installation et Configuration

Installer et mettre en oeuvre le classe, il suffit de :
1/ Télécharger la classe :

$ wget 'http://sourceforge.net/tracker/download.php?group_id=126371&atid=705494&file_id=180054&aid=1498241'  -O php_rest_sql.tar.gz

2/ L’extracter dans votre arborescence Web :

tar xzvf php_rest_sql.tar.gz -C /var/www

3/ Editer le fichier de configuration phprestsql.ini.

4/ Editer un fichier .htacces et activer le module rewrite dans Apache.

Et voila !
Vous pouvez accéder au contenu de votre base de données directement à l’aide d’un navigateur.

Il ne vous reste plus qu’à écrire un client pour accéder aux données, à l’aide de la bibilothèque PHP CURL par exemple.

Conclusion

J’ai soumis mon patch à Paul James, l’auteur du projet et proposé l’idée de transformer celui-ci en module Pear. Il faut savoir que l’auteur a développé le project Tonic autour du même concept.

Mais il s’agit d’un veritable framework de développement web et qui par conséquent est beaucoup plus intrusif.

Filed under: Programming — Tags:, , — cscm @ 10:51

February 4, 2006

sqlite_fetch_object for PHP4

The sqlite_fetch_object function is not implemented in the PECL extension version 1.0.3.
I’ve rewrite it sqlite_fetch_object in PHP :

// An empty class
class bidon {
}

// Fetch resultset as an object
function sqlite_fetch_object(&$resource){
                $arr =  sqlite_fetch_array($resource);
                $obj = new bidon();
                foreach ($arr as $key => $value) {
                        # Check is valid $T_VARIABLE
                        if (ereg("[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*", $key)) {
                                $obj->$key;
                        }
                }
                return $obj;
}

Voila

Filed under: Programming — Tags: — cscm @ 13:30

Powered by WordPress