| Linuxman - novembre 1999 |
2 11 1999
11 11 1999
12 11 1999
14 11 1999
15 11 1999
20 11 1999
22 11 1999
| 2 11 1999 |
L'autre matin je suis allé voir Jeanne d'Arc au cinoche, il était encore bien tôt dans le froid matinal mais cela ne m'a couté que 27 balles alors je me suis dit que pour 20 min de pub et 2h40 de film, soit 3h à 9 francs de l'heure, cela valait la peine... Au début je me suis dit que je n'en parlerai pas parce que j'ai beaucoup de mal à juger le film, mais bon, ce soir je suis bien installé dans mon lit avec mon laptop sur les genoux alors je veux bien faire un petit effort...
Un critère qui me permet généralement de noter rapidement un film est si je l'ai trouvé long ou pas. J'ai trouvé Jeanne d'Arc très court, signe que je me suis laissé entraîné dans le scénario et qu'il avait donc suffisamment de tenant pour ne pas trouver le temps long. Mais une autre raison pour laquelle j'ai pu ne pas trouver le temps long, c'est que j'ai cogité tout le long pour essayer de comprendre le personnage de Leeloo, euh, pardon, Jeanne, enfin c'est pareil.
Un point qui ressort un peu de mes profondes cogitations, c'est qu'il ne faut pas aller voir le film pour voir une quelconque représentation de Dieu, de toutes les façons notre ami Luc n'en sais pas plus sur le sujet qu'un autre, mais c'est bien Leeloo qu'il faut trouver, elle et elle seule, parce qu'il n'y a rien d'autre qu'elle dans ce film, pas de Dieu, pas de héros, pas de miracles, juste la vie de Jeanne. Et là ou je reconnais le mérite de Luc, c'est qu'il a su traiter le sujet sans prendre de décision, sans montrer ce qu'il s'était ou non passé, il a juste présenté les faits.
C'est la dernière partie du film qui permet de comprendre que finalement que Jeanne ait entendu des voix ou pas, quelle importance ? Tout n'est que l'interprétation que l'on fait de faits qui nous sont présentés. Et finalement chacun trouvera dans sa vie de tous les jours des dizaines de signes qui pourraient s'interpréter d'une façon ou d'une autre, mais qui finalement ne sont peut être rien d'autre que des coïncidences plus ou moins heureuses.
Et voix ou pas, la morale de l'histoire, c'est que c'est la foix en quelque chose qui permet à certains de faire ce que d'autres ne pourront jamais. Le pragmatisme permet certes d'aborder la vie avec calme et sérénité, mais le pragmatisme ne permet certainement pas de déplacer les montagnes.
Pour conclure cette courte mais néanmoins profonde réflexion en ce 2 Novembre, je dirai que ce film est pas mal, mais peut être pas pour les raisons historiques ou autres qui y sont attachées, plutôt pour essayer de comprendre ce qui fait nous fait avancer et mourir pour une cause, et si tout cela en vaut la peine...
| 11 11 1999 |
Mots Clés : burnallgif, png, gif2png, burnallgif.
Je viens de me rendre compte d'avoir perdu l'article du 6 novembre où par là causant de la journée du 5 consacrée au "Burn All Gifs Day". Cette journée devait voir les images au format GIF des sites web transformées en PNG pour parer la demande de droits d'Unisys, propriétaire de la compression utilisée pour ce format GIF. En conséquence le site BurnAllGif.org donne accès à des outils permettant de convertir une image GIF en PNG (gif2png) ou l'ensemble d'un site web (web2png). La seule restriction concerne les images GIF contenant des parties transparentes. Ces images ne sont pas converties par l'outil web2png du fait de leur incompatibilité actuelle avec les bro^H^H^Hbutineurs courants.
Remarque : le paragraphe précédent est à lire sur un ton monocorde, genre blasé de la vie, parce que c'est un peu dans cet esprit que je l'ai écrit, un peu plus d'enthousiasme dans l'avenir je promets d'avoir (je ne me la joue pas Yoda c'est juste que j'ai pensé la fin de la phrase avant le début et revenir en arrière est assez pénible je dois dire, remarquez que c'est pour cela que Yoda doit causer un peu comme cela, comme il est plutôt du genre en avance intellectuellement, il commence a dire la fin de sa phrase et puis il se rend compte qu'il n'avait pas encore dit le début, alors il tourne cela un peu a la Woualegain histoire de se faire quand même comprendre, parce que pas savoir parler pour un Jedi c'est quand même un peu la honte :).
J'avais pas mal d'espoirs et d'attentes avant d'aller voir ce film, et s'il n'est finalement pas du tout comme je l'avais imaginé, il n'en reste pas moins pas si mal. Il est d'une durée correcte (2h 30), et assez bien mené ma foix. Les idées du films sont assez basiques : le retour aux valeurs humaines, à la connaissance de soi. Meme si la vision globale du film peut laisser apparaître quelques incohérences, cela reste toutefois assez habile. Je repprocherai quand même un peu la docilité de tous les membres du fight club qui, meme s'ils ne sont pas vraiment la base du scénario, apparaissent comme vraiment trop basiques. Cela aurait considérablement complexifiée la chose que de représenter chaque personnage d'un façon aussi tourmentée que le personnage principal lui-même, mais c'est pourtant la réalité.
Bref, allez voir le film, mais ne vous attardez pas sur des détails de l'histoire, demandez vous juste ce qui vous pousse, vous, à ne pas penser la même chose et à prendre un peu de recul sur vos pseudo problèmes quotidiens. A vrai dire, j'ai vu Jeanne d'Arc il y a pas très longtemps, et finalement ce que l'on peut tirer de ces deux films est très semblable, à savoir que l'on a besoin de croire en quelque chose ou quelqu'un, quelque chose ou quelqu'un qu'on ne peut malheureusement pas acheter...
Ceux qui ont l'oeil aiguisé auront peut-être remarqué (je me permet de dire ceux parce que je connais au moins 3 personnes qui lisent ce site (oui 3 vous avez bien lu), auxquelles je dis bonjour d'ailleurs :) au bas de la page la ligne Generated truc truc truc qui laisse supposer une création automatique de cette page. Et je dis d'autant plus bonjour que la raison de cet article est liée a un commentaire de l'un d'entre vous qui me demandait comment était géré les pages de mon site (base de données, scripts...). C'est bien embéter et plein d'une honte certaine que je répondais modestement : hum, xemacs ?
C'est alors, que mon amour propre blessé j'ai vite corrigé cette erreur en me suis attelé à passer tout cela sous une base de données avec, effectivement, quelques scripts Perl pour gérer le tout. Donc après un week end un peu chargé je l'avoue c'est sans honte aucune je n'utilise maintenant plus que vi pour taper cet article qui sera par la suite intégrer via un script Perl dans une base de données Postgresql avant d'être de nouveau mis en forme avec un autre script dans la page que vous lisez actuellement.
Si la quantité de données de ce site, qui doit avoisiner le demi méga octet de texte, est bien loin d'exiger la mise en place d'une base de données et aurait sans doute pu se contenter d'un ou deux scripts, il n'empèche que toute occasion est bonne a prendre pour s'enrichir un peu, parce que soyez en conscients, ce qui se vend aujourd'hui et qui se vendra encore plus demain, c'est la connaissance et la compétence technique. Si les gens néanmoins fort bien habillés du marketting continueront à ramasser gros, il est fort à parier que le role de guru sera un placement on ne peut plus profitable dans un monde ou la complexité technique augmente exponentiellement.
Si les quelques essais jusqu'à présent ont révélé que tout semblait fonctionner sans trop de dégât, je ne peux pas encore certifié ni la validité de l'architecture mise en place ni de son efficacité, mais je pense que le fait de détailler tout cela me permettra de mettre à jour quelques défauts et d'autre part cela donne un support intéressant sans être trop complexe pour parler un peu de SQL, d'HTML et de Perl.
Mais, comme dirait un ami à moi, il ne faut pas mélanger les torchons et les chemises. C'est donc sur ces bonnes paroles que je m'en retourne pioncer un chouillat pour me conformer à cette bonne vieille règle mais finalement toujours d'actualité stipulant que puisque les journées ont 24 h, autant se baser sur se rythme pour organiser son temps, on y gagne en lumière, et on est socialement beaucoup mieux considéré, et de nos jours, la considération sociale, il ne faut pas cracher dessus, croyez moi...
| 12 11 1999 |
Mots Clés : linuxman, Perl, Postgresql, SQL, linuxman.
Petit exercice donc pour ceux qui suivent, contruction de ce site avec :
Une base de donnée
Un chouillat de SQL
Un peu de Perl
Un brin de connaissance en HTML
Base de données
A vrai dire le choix de la base de données s'est un peu fait de lui même dans le sens où j'ai simplement regarder ce qu'il y avait d'installé sur ma babasse. Il se trouve que l'heureux élu était PostgreSQL 6.5 quelquechose. Peu exigent du côté performance ou fonctionnalité, je n'ai pas passé des heures à le comparer à son rival, MySQL, qui selon le peu que j'ai lu fourni de bien meilleure performance au dépend de quelques fonctionnalité pour les bases de petites capacités. Tout deux sont disponibles sous GPL, donc peu de soucis, et se trouve partout où il est bon de se ressourcer de temps en temps.
Rien de bien compliqué dans la mise en place de PostgreSQL, les binaires fournispermettent facilement d'initialiser la chose. Il suffit en effet de taper /etc/rc.d/init.d/postgresql start qui lance le serveur et lors du premier lancement initialise correctement la base. Après devenir l'utilisateur postgres il faut pour ajouter votre utilisateur comme utilisateur postgres et, selon votre bonté instantanée, lui donner ou non les droits de créer, détruire ou super-utilisateur postgres.
Une fois redevenu votre inoffensif petit utilisateur, vous voilà donc prêt à jouer un peu avec votre tout nouveau serveur de bases de données, aidé bien entendu par la prolifique documentation trouvée dans /usr/doc/postgresql-version/. La première étape consiste à créer la base, appelée linuxman, c'est original je sais, en tapant createdb linuxman.
Je ne m'aventurerai pas dans une description du langage SQL, vu mes immenses connaissances dans ce domaines, et me contenterai de quelques commandes, certes sommaires et surement perfectibles, mais néanmoins suffisante pour causer tranquille avec son petit serveur sans recevoir inlassablement des refus à nos requêtes. Dans un premier temps il nous faut trouver le futur contenu de cette base de données. Sans trop exploser le load de mes neurones je trouve qu'il faut une entrée par mots clés. Une entrées par articles entraînant des recherches difficiles sur les mots clés. Les informations associées à ce mots clés, sont la date et l'article correspondant. Après des essais infructueux avec le format date de postgresql je me resouds à utiliser 3 entiers pour l'année, le mois et le jour, et un de plus pour le numéro de l'article un jour donné. Postgresql n'accepte pas d'entrée de type standart d'une taille supérieure à 8192 octets ; c'est donc le type large object qui sera attribué aux a rticles, qui n'est autre qu'un découpage interne de l'objet donnée et qui est alors référencé par un identificateur récupéré lors de la création de cet objet.
Donc, pour résumer, la table, appelé articles (noter l'originalité :), se présente sous la forme suivante :
year : int2
month : int2
day : int2
num : int2
keyword : text
article : oid
Le type int2 est un entier 16 bits, suffisant pour mon utilisation et même trop grand pour le mois et le jour (ce qui ne manque pas de me complexer, mais ma quête effreinée de l'optimisation de la place ne m'a renvoyé que vers des pertes de performances du à des calculs supplémentaires et c'est sur les paroles sages d'un ami : Aujourd'hui les octets ça coute que dalle que je me suis résolu à cet echec, certes mineur, mais échec tout de même). Le mot clé est un format texte classique et l'article, comme expliqué plus haut, est un pointeur vers un objet stocké ailleurs dans la base.
Pour créer cette table à l'intérieur de la base de données linuxman préalablement initialisée, rien de plus simple, tout d'abord on se loggue dans la base avec psql linuxman qui nous donne accés à un environnement d'où l'on peut interroger et modifier la base. Ensuite c'est la commande CREATE qui fera votre bonheur :
CREATE TABLE articles (year int2, month int2, day int2, num int2, keyword text, article oid);
Une fois la table créer, et emplie de l'envie frémissante de la remplir, un INSERT INTO articles VALUES ('1999','11','12','1','coucou'); permet de rajouter une ligne, partielle la ligne, vu que je n'ai pas renseigné le champ article. Pour une insertion encore plus parsemée, un INSERT INTO articles (year,day) VALUES ('1999','3'); vous comblera de joie.
Il commence à se faire bien trop tard pour mes vieux os, et au risque de choquer les demoiselles, je vous tire ma réverence pour aujourd'hui et terminerai cette aventure pleine de suspence insoutenable sous peu...
| 14 11 1999 |
Mots Clés : linuxman, Postgresql, linuxman.
Continuons donc à nous amuser avec un peu de SQL, de toutes les façons c'est trop humide hors de la demeure... Après avoir insérer les quelques premières lignesdans votre flamband neuve base de données, viendra le temps de la requête. C'est alors que seront de rigueur les :
SELECT * FROM articles;
SELECT year,month FROM articles WHERE year = '1999' AND day = '12';
SELECT day,month,year,keyword FROM articles WHERE year = '1999' GROUP BY day,month,year,keyword ORDER BY month;
DELETE FROM articles;
DELETE FROM articles WHERE year='1876';
Cela se passe d'explication et reste assez basique, me suffisant en tout cas pour mes maigres besoins. Les aides fournies permettront d'approfondir un peu si besoin est.
La gestion des gros objets est différencié et reste je pense spécifique à postgresql, importer un nouvel objet, l'exporter ou le supprimer se fait par :
SELECT lo_import("/tmp/file");
SELECT lo_export(oid,"/tmp/file");
SELECT lo_unlink(oid);
Pour compléter la base il me faut maintenant rajouter une table qui contiendra les différents fichiers en attachements que je peux associer à certains articles. La table est finalement proche de articles et ressemble à :
CREATE TABLE "attachments" {
"year" int2,
"month" int2,
"day" int2,
"num" int2,
"name" text,
"attachment" oid);
Ceci terminera ce leger aperçu de la base basique (prenons nos précautions) en SQL, en tous les cas cela m'a suffit...
| 15 11 1999 |
Mots Clés : Postgresql, SQL, Perl, Postgresql.
Perl est mon ami, enfin, disons que je vois qui c'est :)
Maintenant que je vous ai décrit à peu près les commandes utiles en SQL pour le problème posé, reste à automatiser tout cela avec quelques scripts Perl. Après consultation des oracles, se révèlent nécessaire 4 scripts :
Un pour insérer un article dans la base
Un enlever un article de la base
Un pour générer les pages HTML
Un pour regénérer les articles à partir des pages HTML
Pour le moment les scripts que j'ai faits sont on ne peut plus basiques, sans options ni même vérification. Bref c'est du brouillon mais bon, l'idée y est. D'autre part je ne suis pas non plus un kador de Perl, donc les scripts marchent, mais après je n'ai pas cherché l'optimisation à tout va ni la clarté transcendante du code. Disons que cela constitue un point de départ.
insert.pl
#!/usr/bin/perl
$filename=$ARGV[0];
$dir = $filename;
$dir =~ s#[^/]*$##;
$db="linuxman";
Tout d'abord je prends le premier argument qui est l'article à insérer, qui se présente de la façcon suivante :
Première ligne : an mois jour num sous la forme 19991115-1
Deuxième ligne : mots clés séparés par des virgules
Troisième lignes : attachements séparés par des virgules
Et puis le reste c'est l'articles html proprement diti.
Avec ce premier argument j'extrais le chemin (avec s#[^/]*$## je ne garde que ce qu'il y a après le dernier / (je rappelle au passage que n'importe quel caractère peut remplacer les / dans une expression régulière)).
use Pg;
$conn = Pg::connectdb("dbname=$db");
die $conn->errorMessage unless PGRES_CONNECTION_OK eq $conn->status;
print "connected to $db\n";
Pg est le package permettant les accés au serveur PostgreSQL. La connection à la base est on ne peut plus simple et se fait avec la fonction connectdb de Pg. Elle retourne un objet connection qui permettra par la suite d'interroger et modifier la base.
open(FD, "<$filename") or die "can not open $filename";
$filename contient mon article.
$_=<FD>;
/(\d{4})(\d{2})(\d{2})-(\d+)/;
$year=$1;
$month=$2;
$day=$3;
$numero=$4;
La première ligne contient la date et le numéro de l'article.
$_=<FD>;
s/\s+$//g;
s/^\s+//g;
s/\s*,\s*/,/g;
s/'/\\'/g;
@keywords = split (',',$_);
La deuxième ligne contient les mots clés. J'enlève au passage les espaces inutiles et backslashe les apostrophes.
$_=<FD>;
s/\s+$//g;
s/^\s+//g;
s/\s*,\s*/,/g;
s/'/\\'/g;
@attachments = split (',',$_);
La troisième ligne contient la liste des attachements.
$result = $conn->exec("SELECT num FROM articles WHERE year = '$year' AND month = '$month' AND day = '$day' GROUP BY num");
die $conn->errorMessage unless PGRES_TUPLES_OK eq $result->resultStatus;
$num = $result->ntuples+1;
($num==$numero) or die "Error between the given num ($numero) and the calculated one ($num)";
Je vérifie avec une requête à la base que le numéro d'article fourni n'existe pas déjà dans la base.
while (<FD>) {
encode();
$line="$line$_";
}
Je lis l'article et le met dans $line. La fonction encode se contente de remplacer les accents et autres singularités par les codes HTML correspondant (défini à la fin du programme).
$result = $conn->exec("BEGIN");
die $conn->errorMessage unless PGRES_COMMAND_OK eq $result->resultStatus;
$oid = $conn->lo_creat(0644) or die $conn->errorMessage;
$ofd = $conn->lo_open($oid,0644);
die $conn->errorMessage if $ofd==-1;
$len = length($line);
print "Creating article $oid, length $len\n";
die $conn->errorMessage unless $conn->lo_write($ofd,$line,$len) == $len;
$result = $conn->exec("END");
die $conn->errorMessage unless PGRES_COMMAND_OK eq $result->resultStatus;
Je lance le mode commande pour créer un nouveau gros objet (lo=large object), en récupérer le oid et y copier l'article stocké dans $line.
for ($i = 0; $i<@keywords;$i++){
$result = $conn->exec("INSERT INTO articles VALUES ('$year','$month','$day','$num','$keywords[$i]','$oid')");
die $conn->errorMessage unless PGRES_COMMAND_OK eq $result->resultStatus;
}
Je crée une entrée dans la table articles pour chaque mot clé.
for ($i=0;$i<@attachments;$i++){
$result = $conn->exec("BEGIN");
die $conn->errorMessage unless PGRES_COMMAND_OK eq $result->resultStatus;
$oid = $conn->lo_import("$dir$attachments[$i]") or die $conn->errorMessage;
$result = $conn->exec("END");
die $conn->errorMessage unless PGRES_COMMAND_OK eq $result->resultStatus;
print "Adding entry for attachments $attachments[$i]\n";
$result = $conn->exec("INSERT INTO attachments VALUES ('$year','$month','$day','$num','$attachments[$i]','$oid')");
die $conn->errorMessage unless PGRES_COMMAND_OK eq $result->resultStatus;
}
Je crée une entrée pour chaque attachement dans la table attachments d'une façon semblable à celle pour les articles. Voilà maintenant venir la fonction encode :
sub encode {
s/(\s| )\s/ /g;
s/é/é/g;
s/è/è/g;
s/ê/ê/g;
s/ë/ë/g;
s/à/à/g;
s/â/â/g;
s/ä/ä/g;
s/ù/ù/g;
s/û/û/g;
s/ü/ü/g;
s/ô/ô/g;
s/ö/ö/g;
s/ï/ï/g;
s/î/î/g;
s/ç/ç/g;
return $_;
}
Voila pour le premier script que j'ai bien détaillé pour voir un peu tous les aspects de la chose, je ne sais pas si je serais aussi méticuleux par la suite, enfin nous verrons, mais là, dodo :)
| 20 11 1999 |
Mots Clés : Postgresql, Perl, Postgresql.
Pour terminer ce petit exercice d'interfaçage entre PostgreSQL et un site web simple, et puisqu'il ne fait pas beau, je vais rapidement décrire les trois autres scripts utilisés pour mettre en oeuvre la chose, à savoir un script pour enlever un article précédemment entrés dans la base, un script pour générer les pages HTML et un script pour retrouver les articles à partir des pages HTML.
remove.pl
Ce script est finalement bien utile pour enlever un article de la base, corriger quelques fautes diverses et ensuite le remettre sans soucis avec insert.pl. Sans détailler le script tout entier, je vais quand même donner les principales étapes. Le script prend un argument qui identifie l'article et se présente sous la forme YYYYMMDD-NUM du genre 19991120-1.
Après s'être connecter à la base, on vérifie tout d'abord que l'on ne s'est pas profondemment ramassé dans le nom de l'article :
$result = $conn->exec("SELECT article FROM articles WHERE year = '$year' AND month = '$month' AND day = '$day' AND num='$num'");
die $conn->errorMessage unless PGRES_TUPLES_OK eq $result->resultStatus;
if ($result->ntuples>0) {
...
Ceci fait l'entrée correspondante est donc répartie dans les différents champs de $result. Tout d'abord récupérer le oid de l'article et l'éliminer :
$oid = $result->getvalue(0,0);
die $conn->errorMessage if (-1 == $conn->lo_unlink($oid));
Ensuite effacer l'entrée dans la table article :
$result = $conn->exec("DELETE FROM articles WHERE year = '$year' AND month = '$month' AND day = '$day' AND num='$num'");
die $conn->errorMessage unless 1==$result->resultStatus;
Et puis, le fin du fin, on détruit les éventuels attachements sans pitié :
$result = $conn->exec("SELECT attachment FROM attachments WHERE year = '$year' AND month = '$month' AND day = '$day' AND num='$num'");
die $conn->errorMessage unless PGRES_TUPLES_OK eq $result->resultStatus;
for ($i=0;$i<$result->ntuples;$i++){
$oid = $result->getvalue($i,0);
die $conn->errorMessage if -1 == $conn->lo_unlink($oid);
}
$result = $conn->exec("DELETE FROM attachments WHERE year = '$year' AND month = '$month' AND day = '$day' AND num='$num'");
die $conn->errorMessage unless 1==$result->resultStatus;
Voilà donc comment enlever un article de la base, on peut imaginer sur ce modèle tout type d'améliorations, enlever toute une année, tout un mois... Ce n'est pas très compliqué à rajouter mais je n'en ai pas eu vraiment besoin pour l'instant.
generate.pl
Ce script régénère l'ensemble du site à partir de la base. Il est principalement composé de code HTML et ne comporte pas, que je me souvienne, de subtilité majeure... Alors, la date de génération est formatée est sauvée dans une variable grâce à :
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$gendate=sprintf "%04d-%02d-%02d, %02dh%02d",1900+$year,$mon+1,$mday,$hour,$min;
Je sauve ensuite l'ensemble des mois à générer dans un tableau à deux dimensions :
$result = $conn->exec("SELECT year,month FROM articles GROUP BY year,month ORDER BY year");
die $conn->errorMessage unless PGRES_TUPLES_OK eq $result->resultStatus;
$num = $result->ntuples;
for ($i=0;$i<$num;$i++){
$tab[$i][0]=$result->getvalue($i,0);
$tab[$i][1]=$result->getvalue($i,1);
}
Une boucle permet alors de générer les mois un par un :
for ($i=0;$i<$num;$i++){
create($i);
}
La sous routine create fait tout le boulot. Tout d'abord le répertoire adéquat est créer et le fichier HTML ouvert :
my($i)= @_; # permet de récupérer les arguments passés à la sous-routine.
$an=$tab[$i][0];
$mois=$tab[$i][1];
$pref = sprintf "%04d%02d",$an,$mois;
print "create $pref/$pref.html\n";
mkdir("$pref", 0755);
$filename="$pref/$pref.html";
open(FD, ">$filename") or die "can not open $filename";
Une fois le fichier ouvert, il n'y a plus qu'à revoir ses leçons d'HTML :
print FD "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">
<html>
<head>
<title>Linuxman - $mois[$mois] $an</title>
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">
<meta name=\"description\" content=\"petits articles sur Linux\">
<meta name=\"keywords\" content=\"linux,aide\">
<meta name=\"Author\" content=\"Warly\">
</head>
<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000EE\" vlink=\"#551A8B\" alink=\"#FF0000\">
<a name=\"top\"></a>
<table width=\"99%\" border=0 cellspacing=0 cellpadding=0>
<tbody><tr><td valign=top bgcolor=#003388>
<font size=-1 color=#FFFFFF><b>Linuxman - $mois[$mois] $an</b></font>
</td></tr></tbody>
</table>
<br>
<br>
<font size=\"-1\"><a href=\"../index.html\">INDEX</a></font>\n";
Entête on ne peut plus classique d'un fichier HTML avec cependant une petite différenciation par le mois courant qui est stocké dans un tableau et inséré au bon endroit (je vous explique pas comment je galère pour les tags < et >, en écrivant ; il doit y avoir moyen de faire un petit parser pour m'éviter cette galère, il faudra que j'y réfléchisse un peu)... Bon continuons plein de joie, hum, hum... La suite place ou non les liens vers les mois suivant et précédent selon le mois actuel :
if ($i>0) {
$s = sprintf "%04d%02d",$tab[$i-1][0],$tab[$i-1][1];
print FD "<p><font size=\"-1\"><a href=\"../$s/$s.html\">Mois précédent</a>
</font></p>\n";
}
if (($i+1)<@tab) {
$s = sprintf "%04d%02d",$tab[$i+1][0],$tab[$i+1][1];
print FD "<p><font size=\"-1\"><a href=\"../$s/$s.html\">Mois suivant</a>
</font></p>\n";
}
Après avoir récupérer par une requête les différents jours où il existe des articles pour ce mois ci, je crée les liens du début du fichier :
for ($j=0;$j<$n_day;$j++){
$jour[$j]=$result->getvalue($j,0);
$tag = sprintf "%04d%02d%02d",$an,$mois,$jour[$j];
print FD "<br><a href=\"#$tag\">$jour[$j] $mois $an</a>\n";
}
Puis pour chaque jour je crée les articles existants :
for ($j=0;$j<$n_day;$j++){
$r_data = $conn->exec("SELECT num FROM articles WHERE year = $an AND month = $mois AND day = $jour[$j] GROUP BY num");
die $conn->errorMessage unless PGRES_TUPLES_OK eq $r_data->resultStatus;
$n_art = $r_data->ntuples;
print "$n_art articles for $jour[$j] $mois[$mois] $an\n";
$tag = sprintf "%04d%02d%02d",$an,$mois,$jour[$j];
print FD "<p></p><table width=\"99%\" border=0 cellspacing=0 cellpadding=0>
<tbody><tr><td valign=top bgcolor=#003388>
<font size=-1 color=#FFFFFF><b><a name=$tag></a> $jour[$j] $mois $an</b></font>
</td></tr></tbody>
</table>\n";
Ceci est l'entête standart pour un jour, maintenant je mets tous les articles à la suite pour ce jour :
for ($k=0;$k<$n_art;$k++){
$numero = $k+1;
print FD "<p><font size=-1><b><a name=$tag-$numero></a>Mots Clés : ";
$r_data = $conn->exec("SELECT keyword,article FROM articles WHERE year = $an AND month = $mois AND day = $jour[$j] AND num = $numero");
die $conn->errorMessage unless PGRES_TUPLES_OK eq $r_data->resultStatus;
$l=0;
for ($l=0;$l<($r_data->ntuples-1);$l++){
$str = $r_data->getvalue($l,0);
print FD "$str, ";
}
$str = $r_data->getvalue($l,0);
print FD "$str.";
print FD "</b></font></p>\n";
$r_com = $conn->exec("BEGIN");
die $conn->errorMessage unless PGRES_COMMAND_OK eq $r_com->resultStatus;
$str = $r_data->getvalue(0,1);
$ofd = $conn->lo_open($str,0644);
die $conn->errorMessage unless $ofd != -1;
while ($conn->lo_read($ofd,$str,1024)){
print FD "$str";
}
$r_com = $result = $conn->exec("END");
die $conn->errorMessage unless PGRES_COMMAND_OK eq $r_com->resultStatus;
print FD "\n<a href=#top><img src=\"../images/3Dup.png\"alt=\"haut de page\" height=8 width=10 border=0></a>\n";
}
Bon j'espère que c'est suffisamment clair, si par malchance il vous faudrait plus d'explications, faîtes le moi savoir. Ensuite lien vers le mois suivant s'il existe et fin du fichier, classique. Pour terminer je sauve les éventuels attachements dans le répertoire si ceux-ci n'existent pas déjà :
$result = $conn->exec("SELECT name,attachment FROM attachments WHERE year = $an AND month = $mois");
die $conn->errorMessage unless PGRES_TUPLES_OK eq $result->resultStatus;
$n_file = $result->ntuples;
for ($j=0;$j<$result->ntuples;$j++){
$name = $result->getvalue($j,0);
if ( ! -e "$name") {
$res = $conn->exec("BEGIN");
die $conn->errorMessage unless PGRES_COMMAND_OK eq $res->resultStatus;
die $conn->errorMessage unless 1 == $conn->lo_export($result->getvalue($j,1), "$pref/$name");
$res = $conn->exec("END");
die $conn->errorMessage unless PGRES_COMMAND_OK eq $res->resultStatus;
}
}
Aucune difficultés à ce niveau là. Cela termine donc la boucle de génération des fichiers mensuels, reste l'index des mots clés et le tour sera joué, et je pourrait enfin aller manger... Non en fait je vais y aller tout de suite parce que j'ai affreusement la famine.
Ha, burb ! Me voilà repus. Bon pour l'index l'entête est classique, ensuite je crée les liens vers les mois :
for ($i=0;$i<$num;$i++){
$an=$tab[$i][0];
$mois=$tab[$i][1];
my($str)= sprintf "%04d%02d",$an,$mois;
print FD "<br><a href=\"$str/$str.html\">$mois[$mois] $an</a>\n";
}
Après avoir affiché les liens je récupère les mots clés et les données associées, le tout classé par ordre alphabétique :
$result = $conn->exec("SELECT year,month,day,num,keyword FROM articles ORDER BY keyword");
die $conn->errorMessage unless PGRES_TUPLES_OK eq $result->resultStatus;
$num_mots_cles = $result->ntuples;
print FD "<table width=80% border=0 cellspacing=20 cellpadding=0>\n";
@lettres = ("Divers","0-9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","\\W");
@alphabet = ("\\W","\\d","aàâä","b","c","d","eéèêêë","f","g","h","iîï","j","k","l","m","n","oôö","p","q","r","s","t","uûüù","v","w","x","yÿ","z");
Les deux listes @lettre et @alphabet servent respectivement à afficher le titre de la section et pour l'expression régulière pour sélectionner les mots clés pout une lettre donnée. Après c'est parti ! (En fait je dois vous avouer un truc, j'aime pas trop les points d'exclamations, c'est assez difficile à psichanalyser, mais j'aime pas trop les points d'exclamation). Je boucle sur les lettres de l'alphabet et pour chaque lettre écris les liens correspondants :
if ($j < $num_mots_cles){
$mot = $result->getvalue($j,4);
while ($mot =~ /^[\/]*[$alphabet[$i-1]].*/i){
$file = sprintf "%04d%02d/%04d%02d.html#%04d%02d%02d-%d",$result->getvalue($j,0),$result->getvalue($j,1),$result->getvalue($j,0),$result->getvalue($j,1),$result->getvalue($j,0),$result->getvalue($j,1),$result->getvalue($j,2),$result->getvalue($j,3);
encode($mot);
print FD "<br><a href=\"$file\">$mot</a>\n";
$j++;
if ($j >= $num_mots_cles) {
last;
}
$mot = $result->getvalue($j,4);
}
}
Et voilà pour les parties principales de generate.pl. Reste maintenant reverse.pl, qui n'a absolument rien d'extraordinaire et recrée les articles de départ à partir des fichiers HTML
reverse.pl
Après avoir ouvert le fichier, celui-ci est parcouru à la recherche de motifs caractéristique d'un début d'article :
while (<FD>){
clean();
if (/<font size=-1 color=#FFFFFF><b><a name=(\d{4})(\d{2})(\d{2})>/){
Cela permet d'obtenir dans $1, $2 et $3 respectivement l'année, le mois et le jour. Ensuite il faut séparer les différents articles pour ce jour, je recherche donc le motif correspondant dans une nouvelle boucle, à l'intérieur de la précédente :
while (<FD>){
clean();
if (/<a name=$year$month$day-(\d+)><\/a>Mots Clés : (.*)[\.]*<\/b><\/font><\/p>/) {
Je récupère ici le numéro de l'article ainsi que les mots clés. Ensuite l'article est parcouru pour d'une part le sauver dans la variable $line mais aussi repérer les attachements éventuels :
$line="";
@attachments = ();
$attachments = "";
while (<FD>){
clean();
if (/<a href=#top>/) {
last;
}
@attachments = (@attachments,/<a href=([^:#\/]+)>/g);
if (/^.+$/) {
$line="$line$_\n";
}
}
for ($i=0;$i<@attachments-1;$i++){
$attachments = "$attachments$attachments[$i], ";
}
if (@attachments) {
$attachments = "$attachments$attachments[@attacments-1]";
}
print OUT "$attachments\n";
print OUT $line;
Bon je détaille pas trop il est plus profitable de chercher un peu par soi-même le fonctionnement pour mieux l'assimiler.
Et bien voilà qui termine ce petit tour d'horizon de comment marche ce site. Je conviens qu'il y a pas mal de boulot de commentaires et d'eclaircissement du code et peut être l'utilisation de méthodes un peu moins archaïques et plus intéractives, j'ai nommé PHP 3 ou mieux, 4, en instance. Mais bon, cela permet de toucher un peu de Perl et un brin de SQL, et c'est déjà pas mal, il faut savoir faire les choses étapes par étapes, cela permet d'avancer plus vite.
| 22 11 1999 |
La vie est ainsi faite que j'ai eu l'opportunité, vendredi, de tester sur mon regretté laptop Corel Linux 1.0. Non que cela soit original ni même rare, mais il est des choses auxquelles, finalement, on ne s'attend pas. Je ne peux pas prétendre cependant avoir étudié le cas en profondeur, m'étant modestement contenté d'une install et de quelques manips.
L'installation est impressionnante de par son interactivité quasi inexistante, à croire que tous est correctement détecté par je ne sais quelle magie. La distribution étonne aussi par sa faible taille, l'image iso se contente en effet d'un demi CD, soit 313 Mo à peine. Mais sachant qu'elle est basée sur une Debian cela n'est après coup que passablement étonnant, la Debian sachant se limiter à l'essentiel assez facilement. Et je peux là faire un repproche à la RedHat 6.1 qui ne saura que laborieusement s'installer sur une configuration minime avec moins de 600 Mo de disque dur.
Donc installation comme une lettre à la poste, reste à voir ce qui a effectivement été bien ou mal configuré. Le manque d'expérience rend la chose un peu partialle mais je dois reconnaître que le serveur X était initialement correctement configuré, et cela dès l'installation, alors qu'une RedHat se limite à un scintillant VGA standart a 60 Hz. Le réseau lui aussi avait eu les faveurs de la bonne augure et fonctionnait du permier coup, tout comme le surprenant double boot linux-NT graphique.
J'oserai cependant critiqué la non configuration du clavier me laissant tristement chercher mes lettres dans mes faibles souvenir du monde, merveilleux s'il en est, du QWERTY. KDE est le bureau par défaut et possèdent une initialisation des plus satisfaisante, tout du moins pour mes faibles exigences, il faut admettre que 2 ans de linux rendent moins regardant j'imagine face à un environnement graphique, et je ne suis pas peu fier de me contenter d'un window manager des plus simple, mais au combien fonctionnel, tel que fvwm2, ou, les fichiers de configuration se faisant complexes de nos jours, d'un enlightenment sans son pesant Gnome.
Le bilan est effectivement positif quant à l'ergonomie et la facilité d'installation ; je redoute cependant un peu les configurations matérielles plus capricieuses qui pourraient plonger l'utilisateur dans un embarras certain.
Warly Home Page
Generated 2000-07-02, 11h31
Mail
Copyright © 1999,2000 Florent Villard (warly@bigfoot.com)
This site was created with daily (tar.gz, rpm)