vendredi 28 décembre 2007

Compilez avant de publier

Avant de publier un composant mason sur votre site (et si vous ne disposez pas d'un serveur dedie au developpement), il peut etre tres utile de le compiler avant pour eliminer les erreurs les plus flagrantes (syntaxe, variables mal declarees ..).

Un petit script bien utile pour compiler vos composants:

  1. !/usr/bin/perl  -w
  2. use strict;
  3. use HTML::Mason;
  4. my $interp = HTML::Mason::Interp->new();
  5. my $file = shift;
  6. eval {
  7.  $interp->make_component(comp_file=>$file);
  8. };
  9. die $@ if $@;
A mettre dans votre ~/bin pour les etrennes :)

5.10 et anniversaire.

Oyez Oyez, en meme temps que l'anniversaire des 20 ans de perl (le bel age), sort la version 5.10 . Cette version a un an de retard, mais la liste des nouveautes vaut le coup d'oeil.

mercredi 19 décembre 2007

5.10 et anniversaire.

Oyez Oyez, en meme temps que l'anniversaire des 20 ans de perl (le bel age), sort la version 5.10 . Cette version a un an de retard, mais la liste des nouveautes vaut le coup d'oeil.

jeudi 29 novembre 2007

Ajax et mason

Faire de l'ajax avec mason est parfaitement possible, meme sans aucune connaissance de la librairie prototype.js . Vous avez quand meme besoin d'installer cette librairie javascript et le la charger dans vos pages. Sur le mason headquarter, vous trouverez un composant ajax tres simple a utiliser. Tout d'abord, downloadez le et sauvegardez le dans votre arborescence de composants (a la racine par exemple). Mettons que son nom dans l'espace mason soit /ajax. Ce composant a deux fonctions:
  • La premiere est qu'il agit en tant que helper pour inclure des appels ajax dans vos pages.
  • La seconde est qu'il s'occupe de l'appel de la methode (une methode mason) du cote serveur lorsque l'evenement ajax est declenche.
La doc du composant est assez claire donc je ne vais pas en dire beaucoup plus. Juste une petite astuce quand meme: lorsque vous declarez quel formulaire serialiser pour faire votre appel ajax, il faut doubler les quotes de l'identifiant du formulaire. Par exemple:
  1. <form id="myform"> ..... </form>
  2. <a href="javascript:<& /ajax, comp=> 'SELF:ajaxservermethod' , form => 'myform' &>">Action</a>
ne fonctionne pas sur tout les navigateurs. Il vous faut ecrire ca:
  1. ..... form => '\'myform\'' .....
C'est tout pour aujourd'hui.

mercredi 28 novembre 2007

Facebook sur la voie de l'internationalisation ?

Pour l'instant, ce n'est pas encore facebook lui même, mais l'application FunWall (slide.com).

On voit apparaitre ça et la quelques mots en français, comme 'choose an image in mes fichiers'.

Je ne sais pas ce que vous en pensez, mais facebook en langue locale, personnellement ça va me faire bizarre. Comment fera-t-on pour comprendre les blagues de nos amis d'autres pays ? Tiens, je vais créer un groupe 'keep facebook english' !!


Powered by ScribeFire.

Quick and dirty encryptage et decryptage

Une fois n'est pas coutume, un peu de code pour encrypter/decrypter des chaines simples rapidement.

  1. sub simplecrypt{
  2. my ($string , $key ) = @_ ;
  3. my $mask = substr($key x length($string), 0 , length($string)) ;
  4. my $crypt = $string ^ $mask ;
  5. return unpack("H*" , $string ^ $mask );
  6. }
  7. sub simpledecrypt{
  8. my ($string , $key ) = @_ ;
  9. my $crypted = pack("H*", $string );
  10. my $mask = substr($key x length($crypted) , 0 , length($crypted));
  11. return $crypted ^ $mask ;
  12. }
Avantage: vraiment simple (base sur un XOR) et surtout independant de tout module supplementaire.

Inconvenient: vraiment trop simple. Le codage XOR n'est pas vraiment connu pour sa securite, impossible d'encrypter des chaines unicode.

Conclusion: A utiliser pour des cryptages de base d'identifiants non confidentiels. Par exemple, si vous faite des urls comme celle ci:

  1. http://www.myserver/article/77.html
et que vous ne voulez pas que vos visiteurs puissent essayer 76, 75 ...

Vous pouvez encrypter le numero avec cette methode.


mercredi 7 novembre 2007

On demande un développeur mason sur paris

C'est assez rare pour le signaler: la société apartia cherche un développeur mason pour bosser sur un gros projet déjà installé chez un client.

Une petite citation de l'annonce parue:

==============================================
I know this is not a jobs list but after seeing the "UK Developers" it
seemed not entirely out of place to say: I am looking for a Mason
developer in Paris (France) to work on a large modular application
already in production at a client's. Pay is good (ie: comensurate with
the rarity of Mason devs). Please contact me at ldm@apartia.fr

Cheers and hail HTML::Mason
=============================================

Si vous êtes dans le coin et que mason n'a plus de secrets pour vous, profitez en !



Powered by ScribeFire.

lundi 15 octobre 2007

Du nouveau chez addthis

Après 2 ou 3 semaines d'interruption de service, l'interface de addthis est de nouveau fonctionnelle avec son lot de nouveautés. Parmi celles-ci, l'ajout facile du widget de bookmarking au bas de chaque post. Bon social bookmarking !

Servir du contenu binaire

Voici comment servir du contenu binaire avec mason (en mode download):

  1. %# file.html
  2. <%init>
  3. use Apache2::Const qw(OK);
  4. my $content = ... ; # Votre contenu binaire
  5. my $mimeType = 'application/pdf' ; # par exemple
  6. my $fileName = 'rapport.pdf' ;
  7. $m->clear_buffer; # On vide le buffer de tout contenu precedant
  8. $r->content_type($mimeType) ; # Reglage du type mime
  9. $r->headers_out->add('Content-Disposition' => "attachment; filename=$fileName");
  10. # Nom du fichier
  11. binmode STDOUT ; #Sortie purement binaire
  12. print STDOUT $content; # Les donnee
  13. $m->abort(OK); # C'est fini
  14. </%init>
Pour afficher le contenu binaire en ligne (par exemple dans le cas d'une image, ou pour provoquer l'affichage d'un pdf par le plugin du navigateur), il suffit de supprimer la ligne 9. Si ca perturbe vos visiteurs d'avoir une ressource en .html qui sert un pdf, vous pouvez toujours appeller votre fichier file.pdf , et ajouter la chose suivante dans la conf d'apache :
  1. <LocationMatch "/file.pdf$">
  2. SetHandler perl-script
  3. PerlHandler HTML::Mason::ApacheHandler
  4. </LocationMatch>
On spécifie ainsi a apache qu'il doit laisser mason s'occuper de la ressource. C'est tout pour aujourd'hui ! Voir la liste des types mime.

vendredi 12 octobre 2007

Faire un widget pour blogger

Sur l'aide de blogger, on trouve une documentation très bien conçue qui explique ça très bien. On peut mettre ce qu'on veut dans le code du widget. De l'html bien sur, et surtout du javascript pour rendre un contenu dynamiquement. C'est le cas des widgets offres d'emploi de ce blog ! (en bas de page). Pour avoir les vôtres, c'est par ici !

mardi 2 octobre 2007

Composition de page par heritage

La dernière fois, nous avons abordé la composition de page par aggrégation de composants. Ce type de composition est particulierement bien adapté aux composants fonctionnels. Par exemple, une page d'accueil peut être composée des composants "Dernieres news", "Utilisateurs en lignes", "Bloc de publicite", "Edito", "Boite de connexion". Chacun de ces composants apporte une fonctionnalité a la page. Aujourd'hui, je vous propose d'aborder la mise en place d'un layout de page cohérent pour toutes les pages de votre site. Le problème: pouvoir ajouter facilement une page a votre site en gardant le layout general. La solution: utiliser la notion d'heritage de mason pour factoriser le layout global de votre site. L'héritage en mason. Mason permet de définir une chaine d'héritage entre composants. Le composant terminal de cette chaîne d'héritage doit être une page. En fait, la notion d'héritage en mason est un peu éloignée de la notion d'héritage classique que l'on connait dans les langages objets. Pour faire simple, il faudrait plutôt parler d'auto inclusion inversée automatique. Pour être plus clair, prenons un exemple basique: traditionnellement, une page est composée d'un layout global (incluant le header et le footer) et d'un contenu utile. Dans un système à base d'inclusion, on écrierait une page comme ceci:

  1. INCLUDE header
  2. Contenu utile
  3. INCLUDE footer
Avec les fichiers (ou les scripts) header et footer écrits de façon séparée. Cette approche est possible en mason, mais elle n'est pas optimale. En mason, on fait un composant "de base" contenant le layout global de toutes les pages:
  1. %# layout.mas
  2. <html>
  3. <head>
  4. ...
  5. </head>
  6. <body>
  7. ...
  8. % $m->call_next()
  9. ...
  10. </body>
  11. </html>
A la ligne 8, le $m->call_next() permet à mason de continuer dans la chaine d'héritage. Lorsqu'on fait une nouvelle page, il suffit de préciser qu'elle hérite de layout.mas pour que son rendu inclue automatiquement le layout:
  1. %# page.html
  2. <flags>
  3. inherit => '/layout.mas'
  4. </flags>
  5. <p>
  6. Contenu
  7. </p>
Lorsqu'on interroge l'url http://yourserver/page.html , mason va automatiquement inclure le contenu de page.html dans le layout de layout.mas. En ligne 3, on spécifie de quel composant hérite la page. Par défaut, mason assume que toutes les pages héritent d'un composant particulier: autohandler . C'est donc plutôt dans un composant nommé autohandler qu'on va définir le layout global de la page plutôt que dans un layout.mas. De cette façon, on n'a pas besoin de spécifier de quel composant héritent nos pages:
  1. %# autohandler
  2. <html>
  3. <head>
  4. ...
  5. </head>
  6. <body>
  7. ...
  8. % $m->call_next()
  9. ...
  10. </body>
  11. </html>
Ensuite, plus besoin de spéficier l'héritage:
  1. %# page.html
  2. <p>
  3. Contenu
  4. </p>
On voit que de cette manière, ajouter une page qui hérite du layout global est facile. Il suffit de faire une page avec le contenu utile, et elle héritera automatiquement du composant autohandler. La prochaine fois, je vous parlerai des méthodes et de leur comportement dans la chaîne d'héritage. Référence : l'héritage dans le mason book.

samedi 29 septembre 2007

Internationalisation, i18n, unicode et utf8

Aujourd'hui c'est le week end et j'oublie un peu le code. J'ai donc choisi de vous parler de l'internationalisation et de la saine gestion des caractères exotiques. Ceci afin de pouvoir créer des sites qui acceptent et qui affichent n'importe quel caractère. Vous permettrez ainsi à vos visiteurs suédois, polonais, irakiens, tchèques ou japonais de sentir que votre site à été conçu aussi pour eux. Pour vos tests, vous pouvez vous référer à cette page. Pour clarifier les choses, commençons par quelques définitions.

Unicode définit de manière globale ce qu'est un caractère. Unicode définit un numéro, appellé codepoint pour chaque caractère possible sur la planète terre. Vous pouvez voir la liste de ces caractères ici. Par exemple le caractère 'k' est au codepoint 'U+006B' . Le caractère khmer 'dap roc' est situé au codepoint 'U+19FA' . Unicode est donc une manière globale de traiter les caractères de manière abstraite. Depuis perl 5.8, perl est compatible avec unicode. Ainsi pour faire faire une chaine composée des deux caractères cités en exemple, on peut utiliser la notation suivante:

  1. my $kkhmer = "\x{006B}\x{19FA}"
C'est d'ailleurs un moyen pour écrire du code "obsfuscated". Cette chaine kkhmer est donc de longueur 2 en perl. Il existe aussi un moyen d'écrire des caractères unicode sous forme d'entités html: &006B;&19FA; . Le module HTML::Entities vous permet d'automatiser cette transformation, et mason fournit un mécanisme pour la faire automatiquement.

UTF-8 est un encodage. C'est donc un moyen de représenter un caractère sous une forme binaire pour le stockage dans un fichier, la transmission à travers un réseau ou le stockage dans une base de données. Contrairement à l'encodage ISO-8859-1 (plus connu sous le nom latin 1), UTF-8 est capable d'encoder tout les caractères unicodes. Sans rentrer dans les détails, utf-8 encode chaque caractère sur 1 ou plusieurs octets. Beaucoup de problèmes d'encodage proviennent de la confusion entre la notion de chaine unicode et de chaine binaire d'octets encodant ces chaines unicodes. Pour reprendre notre exemple, le caractère 'k' est représenté en UTF-8 par l'octet '6B' et le caractère khmer est représenté par les 3 octets 'xE1xA7xBA' .

Beaucoup de confusions proviennent aussi du fait que pour les caractères purement ascii (comme dans le bon vieux temps), le codepoint unicode, l'encodage UTF-8 et l'encodage latin1 sont identiques. C'est pourquoi on ne se rend compte de ce genre de problème que lorsqu'il commence à y avoir des accents dans le système.

Cas pratique.

Après ces quelques clarifications, construire un système compatible avec les caractères internationaux est beaucoup plus facile. Il suffit de cloisonner les responsabilités et d'assurer que la communication entre les composants du système se fait dans le bon encodage. Pour un exemple concret, nous allons prendre 3 composants: le navigateur web, perl (sous apache) et mysql. Pour chacun de ces composants, on va définir (et assurer) trois choses: l'encodage de sortie, l'encodage d'entrée et la représentation interne.

  • Le navigateur:
    • Encodage d'entrée: Défini à la fois par l'entête HTTP 'Content-Type: text/html; charset=UTF-8' et éventuellement par la balise méta HTML : <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> . Chaque navigateur à un comportement spécifique lorsque ces deux informations ne sont pas identiques. Assurez vous donc qu'elle le sont. Ajoutez la directive AddDefaultCharset UTF-8 Dans votre config d'apache.
    • Encodage de sortie (POST de formulaire ou GET vers le serveur): par défaut c'est le même que l'encodage d'entrée. Il est cependant bon de le spécifier dans chaque formulaire, au cas ou des utilisateurs changerais l'encodage de la page avant d'envoyer leurs informations. Dans chaque formulaire, ajoutez simplement l'attribut accept-charset="UTF-8" .
    • Encodage interne: Normalement, on n'a pas à connaître cette information. Chaque système à fait un choix. L'important c'est que le système puisse traiter des chaines unicode. C'est le cas des navigateurs et de javascript.
  • Perl:
    • Encodage d'entrée (web): Par défaut rien n'est défini. C'est donc des chaines binaires que vous récupérez. Si vous faite du cgi, spécifiez l'encodage au niveau de l'objet $c avec $c->charset('utf-8'). Les appels à $c->param() vous donnerons des chaines perl correctes (unicode). En mason, le problème est identique. J'utilise personnellement la fonction Encode::decode_utf8 sur chaque paramêtre que je sais pouvoir être du texte libre.
    • Encodage de sortie: Par défaut perl encode les chaines en latin1 en sortie. On peur modifier ce comportement avec 'binmode STDOUT , ':utf8' en CGI. En mason, on peut ajouter un filtre à la sortie en ajoutant la directive suivante dans apache: PerlAddVar MasonOutMethod "sub{ binmode STDOUT , ':utf8' ; print @_ ;}"
    • Encodage interne: Comme je l'ai dit précédemment, on ne devrait pas connaitre cette information. Cependant en perl, les chaines unicode internes sont encodées en UTF-8. C'est aussi une source de confusion, puisque ça amène a penser qu'on peut outputer directement une chaine interne. Ce n'est pas le cas (voir point précédent).
  • MySQL:
    • Encodage d'entrée: Aucun. En utilisation avec perl, ce n'est pas génant, étant donné que les chaines internes sont représentées en UTF-8. Lorsqu'on fait un insert ou un update avec le driver MySQL, c'est donc des octets UTF-8 qui sont envoyés et stockés par MySQL.
    • Encodage de sortie: Aucun. C'est donc des octets qu'on obtient par défault lorsqu'on fait un select avec le driver standard. Pour eviter de les décoder à chaque fois et pour obtenir des vraies chaines perl UTF-8, j'ai écrit un patch pour le driver disponible ici. Ce patch a été inclu dans la version officielle du driver à titre expérimental. Activez le décodage UTF-8 automatique comme ceci: $dbh->{'mysql_enable_utf8} = 1
Conclusion:

Grace à ces quelques techniques, vous êtes maintenant en mesure de construire un site compatible avec tout les caractères de la planète. Dans notre cas pratique, on voit que les choses sont nettes concernant le navigateur et perl. MySQL doit certainement être encore amélioré sur ce point. Pour d'autres bases de données, les choses sont plus claires. Par exemple en Postgresql, si on déclare une colonne comme UTF-8, la communication avec perl à travers le driver se fait de manière transparente.

vendredi 28 septembre 2007

Makefile: Modifier une variable pour une cible specifique

Pour modifier une variable pour une cible specifique, on utilise la forme suivante:
  1. cible: <assignement>
  2. cible: dependance
  3. etc..
Par exemple:
  1. prog : CFLAGS = -g
  2. prog : prog.o foo.o bar.o
Dans ce cas, la valeur de CFLAGS sera -g dans le contexte des dependances de prog.

jeudi 27 septembre 2007

Pages et composants mason

En mason, il n'existe pas de difference entre la notion de page et de composant. Une page est simplement un composant qu'on utilise en bout de chaine de traitement mason pour le rendu du code html. Structurellement, un composant est compose d'html, de directives mason, de divers blocs de code perl et eventuellement de methodes et de sous composants. On nomme generalement les composants qui ne sont pas de pages en .mas. Par exemple, voici un composant qui rend la date courante:

  1. % # date.mas
  2. % my $when = gmtime() ;
  3. <p>Page rendue a <% $when %></p>
On inclut ensuite ce composant dans la page index.html ( voir post précèdent ) de la façon suivante:
  1. ...
  2. <& /time.mas &>
  3. ...
Si vous placez ce composant a la racine du serveur, n'importe qui pourrais recuperer votre code a l'adresse http://www.foobar.com/time.mas . Pour eviter cette situation desagreable, l'usage preconise de stocker dans deux repertoires distincts les pages proprement dites et les composants qui ne servent jamais directement comme page. Par exemple, on cree un repertoire masoncomp au meme niveau que htdocs et on ajoute ce repertoire ou mason cherche les composants (dans la conf d'apache):
  1. PerlAddVar MasonCompRoot "components => /var/www/masoncomp/"
On peut alors déplacer le composant time.mas de htdocs vers masoncomp. Pour l'inclure, on utilise toujours '/time.mas' . C'est en quelque sorte son adresse dans l'espace des composants mason. La prochaine fois, je parlerais de composition de page par héritage. En attendant, vous pouvez trouver plus d'information sur les composants ici.

mercredi 26 septembre 2007

Text::Scan et fin de fichier

Si vous utilisez Text::Scan pour scanner des documents contre un dictionnaire et que votre document provient d'un fichier, il faut faire un chomp de $document. En effet Text::Scan considère que la fin de chaîne est l'octet x00 et non pas l'octet x0A qui est la fin de fichier texte.

mardi 25 septembre 2007

Echappement de code html dans les expressions

En general, on utilise la balise <% $expression %> pour afficher une valeur provenant d'une entrée utilisateur, ou bien d'une base de donnée. Si la valeur de $expression contient du code html, cela peut casser votre mise en page ou pire introduire une faille de sécurité XSS. Pour éviter cela, on peut utiliser le module perl HTML::Entities (fonction encode) pour toute les expressions affichées dans la page. Mason offre un mécanisme plus simple pour éviter cette situation. Si vous réglez la variable suivante dans votre config d'apache:

  1. PerlAddVar MasonDefaultEscapeFlags h
Mason protégera tout les caractères nécessaires dans vos expressions en les remplaçant par des entités html. Je vous conseille aussi de regler ce flag d'echappement (h) pour qu'il provoque seulement l'echappement des caracteres purement html. De cette facon, votre code fonctionnera avec tout les character set:
  1. PerlSetVar MasonEscapeFlags "h => \&HTML::Mason::Escapes::basic_html_escape"
Plus d'infos ici (en anglais) Je reviendrais sur les problèmes d'encoding dans un prochain post.

Afficher du code dans blogger

Une astuce pour afficher du code dans blogger sans (trop) se faire mal au cerveau.

  • Pour vos lignes de codes, utilisez le format liste numérotée.
  • Ajoutez un morceau de css dans votre template pour les afficher
Ça donne ça:
  1. .post ol{
  2. white-space: pre ;
  3. font-family: courier;
  4. margin: 0px;
  5. margin-top: 5px;
  6. margin-bottom: 5px;
  7. padding: 10px;
  8. background-color: lightgray;
  9. line-height: 1em;
  10. }
Avantage: les lignes sont numérotées et on peut s'y référer facilement. Inconvénient: On perd l'usage des listes numérotées (franchement, c'est important ?) Ça ne résout cependant pas un problème, c'est l'affichage des &lt; qu'on est oblige d'encoder a la main en &amp;lt; .

Configuration minimale et test avec apache et mod_perl

Une fois apache2 installé, ainsi que mod_perl2 et apreq2 installes, vous devriez avoir dans vos fichiers de conf apache les éléments suivants:

  1. LoadModule perl_module modules/mod_perl.so
  2. LoadModule apreq_module /usr/lib/httpd/modules/mod_apreq2.so
Voyez les liens de references pour l'installation de ces composants. Assurez vous que apache démarre correctement avec ces modules. L'installation de mason se fait de maniere tout a fait classique via cpan. En root, lancez cpan -i HTML::Mason . On peut maintenant passer a la configuration de mason proprement dite dans apache. On charge tout d'abord le handler mason. C'est un handler mod_perl inclu dans mason configurew pour fonctionner comme point d'entree de votre application. On peut noter que l'utilisation de mason ne necessiste aucune connaissance en mod_perl (a part son installation). Toujours dans apache donc:
  1. # Load mason
  2. PerlModule HTML::Mason::ApacheHandler
Ensuite, on doit specifier a mason ou il va trouver les pages a rendre:
  1. PerlAddVar MasonCompRoot "main => /var/www/htdocs/"
Je vous conseille de régler cette variable a la meme valeur que le DocumentRoot de apache pour éviter les confusions. Ensuite, on doit choisir quelles ressources vont etre servies a travers mason. Ceci se fait logiquement au niveau de l'espace des urls. Pour faire simple, nous allons choisir une extension de fichier qui sera toujours servie a travers mason. On peut choisir .html pour rester classique, .mas si vous voulez montrer que vous utilisez mason, .php pour faire comme tout le monde, .jsp pour vendre le produit plus cher ou .axa si vous bossez pour axa. Ici par exemple, on choisi de servir toute les ressources .html au travers de mason:
  1. # Let mason handle html files
  2. <locationmatch>
  3. SetHandler perl-script
  4. PerlHandler HTML::Mason::ApacheHandler
  5. </locationmatch>
Ceci nous laisse la possibilité de faire des pages .htm qui seront elles vraiment statiques si besoin est. Votre première page mason est maintenant a portée de main. Creez un fichier index.html dans votre DocumentRoot, et admirez le resultat.
  1. <html>
  2. <head><body>1 + 1 = <% 1 + 1 %></body>
  3. </html>
Comme vous l'aurez note , la balise <% %> provoque l'évaluation et l'affichage de l'expression perl a l'intérieur. Il y a plusieurs façons d'inclure du code perl a l'intérieur d'une page mason. Pour les détails, c'est par ici(anglais). Voila, c'est tout pour ce billet. La prochaine fois je vous parlerais de composition des pages, de composants et d'héritage.

Introduction a mason.

Je commence ce blog pour pallier au manque d'informations sur mason sur le web français, comme en témoigne cette recherche google. Mason est a la base un moteur de template écrit en perl qui n'a en théorie rien a voir avec le web. On peut d'ailleurs l'utiliser en dehors d'un environnement web pour produire des mails ou encore vos fiches de cuisines préférées en postscript - si on est un vrai geek . On peut donc l'utiliser en environnement perl, apache+cgi , ou encore apache+mod_perl . Au niveau maturite et stabilite, mason n'as rien a envier aux technologies concurrentes; il est utilise pour les pages de amazon et pour de nombreux autre sites a fort trafic. Sur ce blog je vais donc parler principalement de mason dans un environnement web. Le tout sur un mode didactique.