The 2007-11-15 at 19:27 by Loïc d'Anterroches filed under News.
Hier, je faisais savoir que je n’étais pas particulièrement heureux de la gestion des URLs dans Pluf, aujourd’hui, je viens donc de fixer le problème en utilisant encore une fois une approche similaire à celle de Django.
Si vous avez regardé le code du gestionnaire des choses à faire, vous avez pu constater que l’URL d’une vue est utilisée à plusieurs endroits :
Maintenant, la définition de cet URL est à un endroit unique, la correspondance vue <-> URL.
Prenons le cas de l’ajout d’une chose à faire, la vue correspond à la méthode addItem de la class Todo_Views. Et dans la correspondance vue <-> URL on a :
$ctl[] = array('regex' => '#^/list/(\d+)/item/add/$#',
'priority' => 4,
'base' => Pluf::f('todo_base'),
'model' => 'Todo_Views',
'method' => 'addItem');
L’URL en pratique n’est défini que par une expression régulière : #^/list/(\d+)/item/add/$#. Vous pouvez voir le parenthèse qui capture l’id de la liste dans laquelle la chose à faire va être ajouté. Quand je veux utiliser cet URL dans l’action de mon formulaire, je me retrouve avec cette expression régulière et l’id de la liste.
L’expression régulière ici est faite pour extraire l’id de la liste étant donné un URL. On a donc :
/list/23/item/add/ + regex = id de la liste (23)
Maintenant je veux :
/list/23/item/add/.
J’ai donc créé une fonction Pluf_HTTP_URL_buildReverseUrl($url_regex, $params=array()) qui, étant donné l’expression régulière de l’URL et les paramêtres qui seraient extraits par cette expression régulière, reconstitue l’URL.
Donc maintenant, pour obtenir l’URL d’une vue dans le code, je fais simplement :
$url = Pluf_HTTP_URL_urlForView('Todo_Views::addItem', array($list->id));
Cela va directement chercher l’expression régulière dans la définition des vues courantes et passer le tout à mon fonction qui va reconstituer l’URL. Dans un gabarit, c’est tout aussi simple :
<form method="POST" action="{url 'Todo_Views::addItem', array($list.id)}">
Le mieux maintenant, c’est que j’ai défini une fonction qui permet de prendre la correspondance vues <-> URLs d’une application, d’ajouter un préfixe et ainsi de pouvoir l’inclure au sein d’une autre application.
Si vous regardez maintenant le code de l’application exemple, il n’y a presque plus de redondance. La seule chose qui reste à faire, c’est d’extraire du modèle de données Todo_Item ou Todo_List un formulaire de création ou de modification. Pour le moment, il faut encore les définir manuellement et ce n’est pas bien. Voilà du travail pour demain !
The 2007-11-14 at 21:36 by Loïc d'Anterroches filed under News.
Finalement, je viens de mettre à jour l’application de démonstration de Pluf. C’est un gestionnaire de todo lists. Les choses à retenir sont les suivantes :
Le code est divisé en 3 parties :
Je ne suis pas content de la gestion des URLs. Suivez un peu les commentaires de la discussion sur Pluf et Jelix et vous comprendrez vite. Dans le cas de Pluf l’URL est codé à la fois dans la gestion des URLs et dans les vues. Ce n’est pas bien, cela casse le principe de non duplication de l’information. Je vais devoir améliorer ce point dans les jours à venir.
The 2007-11-12 at 20:26 by Loïc d'Anterroches filed under News.
Un lecteur m’a posé la question de savoir que choisir entre Jelix et Pluf. Je n’ai pas de réponse toute faite, car le choix d’un framework est une question de goût. Voici par contre mon avis. Il est bien entendu biaisé puisque je suis le créateur de Pluf. Voici donc une présentation de Pluf et quelques points très limités de Jelix. Je ne connais que peu Jelix.
L’histoire de Pluf est étroitement liée avec mon utilisation du framework Django écrit en Python. En effet, j’ai eu besoin de développer une application complexe avec la contrainte de devoirs utiliser PHP. Je ne pouvais pas utiliser un autre langage. J’ai alors décidé de réimplémenter les éléments que j’appréciais (et apprécie toujours) de Django en PHP.
Avec Pluf vous avez un ORM qui permet de facilement faire des choses genre :
$auteur = new Auteur(); $auteur->nom = 'Loïc'; $auteur->create(); $article = new MonArticle(); $article->titre = 'Mon titre'; $article->contenu = 'Ici un long contenu...'; $article->auteur = $auteur; $article->create(); // Maintenant on recherche les articles écrits par // cet auteur. $articles = $auteur->get_monarticle_list(); assert($articles[0]->id == $article->id);
Les class Auteur et MonArticle doivent simplement étendre la
class de base Pluf_Model. Cela vous donne directement le stockage
possible dans une base de données SQLite, MySQL ou
PostgreSQL.
Après l’ORM, vous avez des vues pour afficher les données et un
controlleur pour faire la sélection de la vue en fonction de
l’URL. Par exemple, vous pouvez dire que l’URL /article/32/
correspond à la méthode afficherArticle de votre class
MesVues. Vous avez un contrôle complet des URL et de leur format
car vous les définissez avec une simple expression régulière. Voici un
extrait :
$ctl[] = array('regex' => '#^/article/(\d+)/$#',
'priority' => 4,
'model' => 'MesVues',
'method' => 'afficherArticle');
La priorité permet de mettre en avant les URL les plus utilisés pour éviter de passer à travers toutes les expressions régulières.
Maintenant pour afficher une page, on peut simplement mettre dans la méthode afficherArticle :
function afficherArticle($request, $match)
{
$article = new MonArticle($match[0]);
$ct = $article->title."\n\n".$article->contenu;
return new Pluf_HTTP_Response($ct, 'text/plain');
}
Voici une méthode très simple qui renvoie même pas de l’HTML, mais simplement le titre et le contenu de l’article. Il n’y a même pas de vérification si l’article demandé existe. Pour faire le contrôle on peut utiliser un raccourci.
function afficherArticle($request, $match)
{
Pluf::loadFunction('Pluf_Shortcuts_GetObjectOr404');
$article = Pluf_Shortcuts_GetObjectOr404('MonArticle', $match[0]);
$ct = $article->title."\n\n".$article->contenu;
return new Pluf_HTTP_Response($ct, 'text/plain');
}
Dans ce cas là, cela voudrait dire que si l’article n’existe pas dans la base de données, une exception de type 404 va être lancée et une erreur 404 sera affichée, sinon la page normale sera affichée.
Le fait d’avoir un objet $request et un objet Pluf_HTTP_Response permet d’avoir des méthodes pour modifier la requête avant la vue et modifier la réponse après la vue. Ce sont les middlewares, ils permettent de faire la gestion des sessions, la validation du code, afficher des informations de debuggage, etc.
Pluf est très léger et permet de facilement utiliser des librairies venant de PEAR.
Avec ceci, vous avez la base de Pluf. Pluf n’impose rien d’autre et en fait vous n’avez même pas besoin d’utiliser tous ces éléments, vous pouvez utiliser juste l’ORM ou juste le dispatcher. Pluf est très léger et généralement vous aurez un process d’environ 2 Mo pour une vue avec l’ORM, le dispatcher, etc.
Maintenant, ce que j’aime dans JELIX. En fait, 2 choses, le système de templates. Tellement sympa que je l’ai repris et étendu pour l’utiliser dans Pluf. L’autre, c’est le principe d’un objet réponse qui assure que la réponse sera toujours comme voulu soit de l’HTML, XML ou Jason.
Le problème que j’ai avec JELIX (note que j’utilise des composants développés par Laurent Jouanneau dont j’apprécie la qualité du code) c’est l’utilisation importante des fichier XML pour ensuite générer dynamiquement des fichiers PHP (alors que PHP 5 permet de faire cela proprement et facilement sans passer par XML) ainsi que l’utilisation importante de conventions qui je trouve "personellement" lourdes :
Par exemple pour supporter un site avec de multiples langues, on se retrouve dans le code avec :
ma_fonction ()
{
$chaine = jLocale::get("bar~foo.buttons.save");
}
là où avec Pluf on a simplement:
ma_fonction ()
{
$chaine = __('Sauvegarder');
}
Par ailleurs l’utilisation importante de ce concept de selecteurs rend le code pour moi difficile à lire et surtout cela devient difficile de faire cohabiter des modules venant de différents auteurs car il faut alors maintenir une configuration pour Jelix et une pour les autres modules qui utilisent normalement des chemins normaux vers les fichiers.
L’autre chose qui m’ennuie c’est le fait d’imposer une structure très particulière pour la position des fichiers .php sur le serveur comment gérer cela avec les modules venant d’autres frameworks ou de PEAR ? C’est possible mais cela ajoute de la complexité.
Dans le cas de Pluf. Une classe MonProject_MaClasse est simplement
dans le fichier MonProjet/MaClasse.php avec le répertoire MonProjet
dans un répertoire qui est dans le PATH de PHP. Mais on peut toujours
faire un "include_once ‘/mon/fichier/class.php’". C’est d’ailleurs la
convention retenue par PEAR pour la version 2 de PEAR.
Maintenant, l’important c’est d’essayer les deux en faisant une petite application. Cela permet de "sentir" si on aime ou pas. En effet, c’est souvent beaucoup une question de goût…
The 2007-11-06 at 10:48 by Loïc d'Anterroches filed under News.
Aujourd’hui, je codais tranquillement quand tout d’un coup, ma validation automatique de mes pages avec tidy me dit :
Warning: <img> escaping malformed URI reference
Oups, étonnant comme message d’erreur. Je regarde mon code :
<img src="logo-conforganizer.png" longdesc="Powered by ConfOrganizer, the conference management and organization software." alt="ConfOrganizer logo" />
Tout semble normal. J’enlève l’attribut longdesc et voilà que l’erreur disparaît. En fait, l’attribut longdesc est un lien vers une information contenant plus de détails sur l’image. Bon, alors comme je ne souhaite pas créer une page pour chacune de mes descriptions, j’ai décidé d’inclure le contenu du lien dans le lien avec le protocole data.
Le résultat :
<img src="logo-conforganizer.png" longdesc="data:text/html;charset=utf-8,Powered%20by%20ConfOrganizer%2C%20the%20conference%20management%20and%20organization%20software." alt="ConfOrganizer logo" />
Si vous voulez en savoir plus sur data: Wikipédia parle du schéma data.
The 2007-11-01 at 09:27 by Loïc d'Anterroches filed under News.
Petite astuce toute simple pour avoir l’équivalent de ucwords pour de l’utf8:
function mb_ucwords($str)
{
return mb_convert_case($str, MB_CASE_TITLE, 'UTF-8');
}
À utiliser ainsi par exemple :
$titre = mb_ucwords(mb_strtolower($titre));
En effet, j’ai souvent des gens qui envoie des articles avec le TITRE TOUT EN MAJUSCULES et je n’aime pas cela. Donc je fais ce petit test :
if ($titre == mb_strtoupper($titre)) {
$titre = mb_ucwords(mb_strtolower($titre));
}
The 2007-10-30 at 13:03 by Loïc d'Anterroches filed under News.
PostgreSQL est un gestionnaire de base de données (RDBMS). C’est l’équivalent d’Oracle en libre. L’application de gestion de conférences que je développe en ce moment est écrite pour supporter toutes les langues avec l’utilisation d’UTF-8 de bout en bout. C’est très bien et cela permet d’utiliser des charactères genre ß, ö, õ, etc. Par contre, maintenant comment stocker ces informations dans la base de données ?
Par exemple, si je pose comme condition que le titre d’un résumé ne doit pas excéder 150 caractères, je pense 150 avec ß équivalent à 1 caractère. Mais avec l’encodage utf-8, cela veut dire que je dois utiliser une déclaration du type "VARCHAR(300)" car les caractères complexes sont en fait stockés sur 2 octets (en fait cela peut aller jusqu’à 6 octets) et que le 300 ici veut dire "une chaîne de caractères de 300 octets de long".
Petit bout de code pour illustrer avant d’aller plus loin :
<?php
header('Content-Type: text/plain; charset=utf-8');
$str = 'ßöpt';
echo('mb_strlen('.$str.')='.mb_strlen($str))."\n";
echo('strlen('.$str.')='.strlen($str))."\n";
Donne :
mb_strlen(ßöpt)=4 strlen(ßöpt)=6
En effet, ß et ö sont stockés sur 2 octets, et, p et t sont stockés sur 1. 2x2+2x1=6, mais on a bien 4 caractères typographiques.
La conclusion est que si j’autorise un titre de 150 caractères de long, il faut faire une déclaration à 150x6=900 "VARCHAR(900)" pour être certain que le titre sera effectivement stocké. Ce n’est pas très élégant.
La bonne nouvelle de PostgreSQL est qu’il est possible de déclarer une colonne de type character varying sans aucune limitation de taille, en ayant toujours la possibilité d’utiliser un index et sans aucune pénalité au niveau performance ! Merci pour ce joli cadeau qui me permet de ne plus avoir à me poser de questions…
The 2007-10-12 at 21:17 by Loïc d'Anterroches filed under News.
Les biocarburants, c’est beau, surtout dans les publicités. Vous voyez des voitures rouler, avec en image de fond un joli champ de blé ou de colza et une petite voix off qui dit : Cette voiture roule propre, avec du biocarburant.
Maintenant, regardons d’un peu plus près. La question est comment produire l’éthanol vert en Europe.
Maintenant regardons de plus près à quel point cet étanol est vert.
La production de blé, maïs ou colza se fait avec :
Ensuite, il faut transporter le tout vers l’usine la plus proche (coût en essence, assez marginal il faut le dire).
La production d’éthanol aujourd’hui est un procédé assez bien maîtrisé est n’entrainant pas de pollution directe majeur, mais il faudrait évaluer l’impact de l’implantation de ces nouvelles usines, le traitement des sols en fin de vie de l’usine, etc. Les risques liés à cette production, il faut en effet des solvants pour la séparation (Benzène entre autres, produit sympatiquement cancérigène).
Maintenant vous avez votre étanol vert. Faites le bilan carbone de cet étanol, en considérant l’ensemble de la chaine de production. Si le bilan est positif, tous les avantages sont détruits par :
Mais pourquoi alors le bioétanol ? Je pense, et c’est mon avis très personnel, que cela sert très bien l’industrie automobile. En effet, cela leur permet d’avoir une image "verte" tout en ne changeant absolument leur comportement et les automobiles misent sur le marché. En effet un moteur aujourd’hui fonctionne très bien avec un mix éthanol/essence conventionnelle. Pour les gouvernements, cela permet de ne pas se remettre en cause et en plus cela fait du soutien aux agriculteurs. Pour les particuliers, utilisateurs finaux, cela donne l’impression de rouler vert et donc cela donne la tranquilité d’esprit de ne pas avoir à changer son comportement.
Maintenant, le bioétanol fonctionne dans certains cas très particuliers. L’un est la production à partir des restes de cannes à sucre au Brésil. Cela fonctionne très bien, mais dans ce cas très particulier, la production provient des résidus, ce qui n’est pas le cas en Europe ou c’est le grain qui est utilisé et non la paille restante.
Au passage, l’augmentation du prix du blé est de l’ordre de 40% en 1 an…
Promis, le prochain billet sera technique, l’utilisation d’Amazon EC2.
The 2007-10-10 at 14:06 by Loïc d'Anterroches filed under News.
En ce moment, je fais de petites expériences avec PHP. Entre autre, je cherche à afficher des équations dans une page web. Pour cela MathML est intéressant, mais il faut dire franchement, latex a une meilleure qualité d’affichage et si j’écris mes équations en latex, je peux ensuite facilement convertir vers un vrai fichier latex pour générer par un exemple un fichier pdf.
La solution est d’utiliser directement latex comme Wikipedia. Le problème est que l’image png avec la formule latex est sur fond blanc et dans mon cas j’ai besoin d’une autre couleur de fond.
Ce que j’obtiens (ici fichier directement pris de la page Wikimedia :
Et ce que je veux (ok, pas cette couleur exacte, mais même principe) :
Je travaille donc avec une image en noir et blanc à la base. Et la solution est la suivante :
$im = imagecreatefrompng('someimage.png');
colorize($im, array('red'=>249, 'green'=>232, 'blue'=>89));
imagepng($im, 'output.png');
imagedestroy($im);
Téléchargez la fonction php pour changer la couleur de l’image.
The 2007-10-06 at 18:08 by Loïc d'Anterroches filed under News.
Les deux développeurs principaux de Mozilla Thunderbird partent vers de nouveaux horizons. Ce n’est pas du joli est cela m’ennuie sérieusement. J’ai conseillé à de nombreuses personnes de migrer vers Thunderbird et maintenant, le projet passe à la trappe. C’est très frustrant. Pour moi, cela ne changera pas grand chose car j’ai déjà migré vers Evolution, mais j’ai l’impression d’avoir mal conseillé de nombreuses personnes, et cela c’est bien la pire des choses.
Au passage, la migration vers Evolution était une bonne idée, un très bonne idée. J’ai fait cette migration pour son intégration dans Gnome et effectivement l’intégration est excellente ! Aujourd’hui je voulais faire des labels pour des enveloppes avec gLabels et bien gLabels permet de directement utiliser un carnet d’adresses d’Evolution, yeah !
The 2007-10-01 at 15:26 by Loïc d'Anterroches filed under News.
En ce moment je teste Evolution. En effet, ce logiciel est bien intégré dans le bureau GNOME. Par exemple quand GNOME détecte une deconnexion du réseau, Evolution passe directement en mode off-line, mes emails sont automatiquement indexés par le moteur de recherches intégré dans GNOME, mon emploi du temps s’affiche directement dans le calendrier lié à l’horloge. Toutes ces petites intégrations rendent l’utilisation d’Evolution plus agréable que Thunderbird. Par contre je regrette l’extension de Thunderbird permettant de facilement bouger un message d’un répertoire à un autre.
Revenons au filtrage des emails avec Bogofilter dans Evolution. Vous devez d’abord l’activer dans les préférences de votre compte email, puis ensuite vous devez l’entrainer. Si vous entrainez quelques centaines de spams et constatez qu’il ne filtre toujours rien, c’est qu’il lui manque des emails qui ne soient pas des spams dans son corpus d’entrainement. La solution est simple : marquez une série d’emails valides comme des spams, puis dans le répertoire des spams marquez les comme non spam. Et voilà, Evolution et Bogofilter vont commencer à faire leur travail très effecicacement.
The 2007-10-01 at 12:45 by Loïc d'Anterroches filed under News.
Après quelques semaines, peut-être mois, à écrire en anglais et à constater que la qualité de mon français dans la vie de tous les jours n’était pas particulièrement resplendissante, j’ai décidé d’écrire de nouveau en français. Je n’écris pas régulièrement c’est vrai, mais ce petit bout de français supplémentaire fera du bien. Ma vie de tous les jours est principalement en allemand, mon travail en anglais, en pratique, le français c’est pour contacter les amis et la famille et parler à mon fils (6 mois, donc bon les sujets sont limités à grosso modo : couche, dodo et mécanique quantique).
Donc voilà, XHTML.net redevient français pour le bonheur de ceux qui peuvent lire ce message et pour les autres et bien je pense que de toute façon ils trouveront leur bonheur ailleurs. Au passage, je trouve sympa de tomber sur des articles techniques en français (comme les publis de maths par exemple), alors un peu plus de web en français, pourquoi pas ?
The 2007-09-11 at 20:43 by Loïc d'Anterroches filed under News.
I am not that efficient because I am enjoying a wonderful time taking care of our son. This little boy is able to suck all my energy in one day and prevent me to fully recover during the night. But, yes, I enjoy it. Johannes will be going to the day care (Kita oder Kindertagesstätte) in October so I will have time to work again…
He is now 6-month old and I am still bad at taking pictures of him, even after 800 shots. Definitely, I am not born to be a people photographer.
The 2007-09-08 at 19:04 by Loïc d'Anterroches filed under News.
The Swiss Federal Office of Public Health has some very interesting data about the electromagnetic fields of several appliances we have at home, like cordless phone, baby monitors or WLAN and energy-saving lamps. La page est aussi disponible en Français.
The 2007-09-04 at 09:34 by Loïc d'Anterroches filed under News.
Voici une caricature de Sarkozy parue d’abord dans le Süddeutschen Zeitung puis repris ici par die Welt am Sonntag, l’édition du week-end du journal Die Welt. Le premier journal est de centre gauche, le dernier de centre droit.
Titre du cartoon: "Le nouveau caniche de Bush."
Bush dit à son père : "Regarde papa !" car manifestement il se prépare à faire faire un tour à son toutou. Cela montre bien la vision qu’ont les Allemands de Sarkozy : à la botte de Bush et ayant un besoin non contrôlé de se montrer, même si ce n’est que pour faire du vent…
The 2007-09-01 at 20:45 by Loïc d'Anterroches filed under News.
When you start a company one of the most important thing to do is to celebrate all the small victories. This is really important. There are so many things that can go wrong, that when you can celebrate something, better not to miss it!
So, after fighting the incredible amount of papers, references and certification requirements of a bank in England, Céondo Ltd eventually got a bank account in good order. This is the first important step for a company, next one is to get a VAT number. So anyway, with a very good friend we ended-up opening a Pommard 1979, du domaine des Charette. Yes, a 28-year-old bottle… and yes we enjoyed it a lot. For the previous one, this was a Champagne 1975, from Paul Gobillard. The next one will be an Armagnac from 1941. And yes, today I am fulfilling my duties too and putting into cave some good bottles I may never taste, but some after me will.
Yes, as advised by my friend Olivier I should really buy a good macro lens.
The 2007-08-29 at 17:52 by Loïc d'Anterroches filed under News.
If you want to netboot Ubuntu Feisty, you can follow my Netboot Guide and just download the Feisty netboot archive:
wget http://archive.ubuntu.com/ubuntu/dists/feisty/main/installer-i386/current/images/netboot/netboot.tar.gz
or from your country mirror, just replace XX with your country code, like fr, de, etc.
wget http://XX.archive.ubuntu.com/ubuntu/dists/feisty/main/installer-i386/current/images/netboot/netboot.tar.gz
It is working like a charm.
The 2007-08-23 at 20:59 by Loïc d'Anterroches filed under News.
You most likely know Thunderbird the email client of the Mozilla Foundation. This is the client I am using at the moment to manage my emails and I must admit, it is a very nice piece of software with the ability to easily extend it with the extension mechanism, but I have a fundamental problem with it: it is not integrated with the Gnome desktop.
Basically Thunderbird is running independently of all the other software on my system. For example it is not easy to get all my contact information in and out of it. I cannot easily create a link to a given email. It is really sad because Evolution, the official Gnome email client, is really slow. So now I am working an half way system, which is basically to store my contact information within EDS using either Evolution or Contacts and Thunderbird to manage my emails. With this approach I can easily export/import my contact information as it is possible to access EDS with Python.
The 2007-08-22 at 16:51 by Loïc d'Anterroches filed under News.
I already talked about the quality of service of Amazon, but I need to say, I had not tested to return some articles I bought but was not satisfied with. Now, I have done it and it works like that:
High quality of service, once again.
The 2007-08-21 at 07:35 by Loïc d'Anterroches filed under News.
At the moment I am looking at hosting providers in Europe for dedicated servers. XHTML.net is running on the Joyent infrastructure, I am very pleased with the quality of the service but the speed of light is a boundary that Joyent cannot beat. If your server is hosted in California and have customers in Germany, the bits need to travel about 10,000 km each way. If you take about 300,000 km/s for the speed of light, you get a minimum 30ms extra time.
In fact, if you do some little tests for a connection between Frankfurt (Germany) and San Diego on the Level3 backbone, you get a consistent 150ms+ travel time for the bits. Do not forget that routing has a cost and the cables are not taking the shortest path.
So, now I want a good hosting provider in Europe. I do not really care about the bandwidth allocation, but I care about its quality. That is, I would be very fine with a 50GB/month base allocation (or less) and then 20cts per extra GB, but I need to have good GB even at 10 in the morning.
Most of the hosting providers are fighting on the price, I am looking for one fighting for the quality, if you know, please tell me, if you don’t know, then I think I will first take one server with Hetzner and another one with OVH, each one being a hot backup of the other. Yes data centres can blackout and that is why I need 2 physically disconnected data centres.
The 2007-08-20 at 20:17 by Loïc d'Anterroches filed under News.
Right now I have to merge some pdf files together. The best tool to do that is pdftk. If you are using a Debian based system, like Ubuntu, just install the pdftk package to use it.
$ sudo apt-get install pdftk
Now, if you want to merge 2 pdf files into one big:
$ pdftk file1.pdf file2.pdf cat output bigpdffile.pdf
And now, why the wonder of apt-get? Just because I am using the experimental Gutsy version of Ubuntu on my laptop, and pdftk is broken on this version. I then tried to run it from my home server, but my home server is running Breezy which is not supported any more. Oups… So I to be able to use pdftk I decided to upgraded my server. Imagine, upgrade from Windows 2000 to Windows XP to use a pdf merger. Crazy no?
No! I got a full upgrade of my server, in just one command and in just 10 minutes:
$ sudo apt-get update && sudo apt-get dist-upgrade
Then
$ sudo apt-get install pdftk
Yeah!