Je dois avouer que je passe un peu plus de temps qu'avant sur mon compte Twitter. Tant qu'à mettre à jour son statut Facebook ou MSN, pourquoi pas celui-là ? En fait, pour faire plus simple, ce sera le seul à l'avenir que je publierai.
En observant ce qui se passait sur Twitter, j'ai découvert quelque chose d'assez drôle : plusieurs membres échangent sur un sujet qui combine deux de mes thèmes préférés, soit la programmation et la musique. En effet, si on recherche #songsincode, on trouvera des énoncés de chansons transcrits en code de différents langages de programmation et ce, en moins de 140 caractères. Certains sont plutôt bien réussis.
Voici quelques extraits :
Nirvana - Smells Like Teen Spirit
select * from song s where s.smells like '%teen spirit%'
Qu'ont-ils vraiment voulu nous dire (à la Macadam tribus) ?
Requête SQL en référence au titre avec une utilisation judicieuse du mot clé LIKE.
AC/DC - Thunderstruck
while(intro){ for(var i==0 ; i<8; i++){ nah() } THUNDER() }
Écoutez l'introduction de la pièce originale, vous comprendrez...
MC Hammer - U Can't Touch This
if (time == (’hammer’)) { this.touchable = false; }
Moment glorieux de sa carrière : Stop, Hammer time! You can't touch this.
Il y a quelques jours, j'ai terminé la lecture du livre Monopoly, The World's Most Famous Game. Ayant souvent joué lorsque j'étais plus jeune, j'avais perdu l'intérêt en vieillissant. Mais lors de mon dernier voyage pour les vacances, ayant plusieurs heures à patienter à bord de l'avion, j'ai acheté ce livre par curiosité lorsque je l'ai vu dans la boutique Virgin de l'aéroport.
J'étais intrigué d'en apprendre davantage sur l'essence du jeu, ses origines, son histoire, ses variations au fil du temps. On a qu'à penser aux récentes versions Monopoly World Edition qui a fait l'objet d'un concours et Monopoly City Streets qui est construit sur la plateforme de Google Maps.
Au début, j'avoue que je l'avais acheté pour tuer le temps, sans avoir l'intention de passer au travers. Mais je me suis fait prendre au jeu et j'ai pris plaisir à le lire en entier. L'auteur, Phil Orbanes, parle en toute connaissance de cause puisqu'il a été le juge en chef des tournois de Monopoly USA et Mondial depuis 1979. Il a retracé l'histoire depuis ses débuts, alors qu'un jeu très semblable du nom de Landlord's Game créé en 1904 par Elizabeth Magie Phillips a fait son chemin jusqu'à devenir une source d'inspiration pour le Monopoly (même si les objectifs de Mme Phillips étaient très différents du destin qu'on lui connait).
Vers 1934, la vision de Charles B. Darrow permet d'imaginer le design du Monopoly tel qu'on le connaît aujourd'hui. Faites le tour des ventes de garage et des bazars car si vous mettez la main sur un Darrow White Box, il pourrait vous rapporter plus de 8000$ auprès des collectionneurs !
P.Orbanes relate en détails l'émergence du jeu, sa commercialisation, l'acquisition des droits par Parker Brothers et le rachat par son concurrent Hasbro. Une galerie d'images d'une trentaine de pages illustre l'évolution du Monopoly à travers le temps, ses versions et certaines annonces publicitaires. À la fin, pour ceux qui seraient intéressés, on retrouve aussi les règles originales du Monopoly telles qu'écrites par Georges Parker (pour simplifier le jeu), l'explication du fonctionnement du Landlord's Game, et aussi celles d'un jeu semblable, Finance.
Tout le monde a déjà joué au moins une fois au Monopoly et tout comme moi, vous avez probablement inventé certaines règles "maison". En relisant les règles, je me rends compte à quel point on s'était écarté des règlements traditionnels!
Je termine en citant au hasard deux sujets dont vous pourrez approfondir les origines au cours de la lecture du livre :
- Les noms des terrains originaux font référence à des rues ou des lieux aux alentours d'Atlantic City aux États-Unis.
- Saviez-vous que la mascotte Mr. Monopoly s'appelait originalement "Rich Uncle Pennybags" ? Il a été dessiné à l'image du banquier J. P. Morgan (lui-même monopoliste).
Si vous développez vos projets PHP avec Zend Framework, il vient un temps où vos fichiers ou votre bootstrap commence à ressembler à ceci :
require_once('Zend/Auth.php');Sinon, les instructions require_once() sont éparpillées dans les pages et les classes selon le besoin, ce qui, à mon avis, n'est pas tout le temps une bonne pratique. À chaque appel de la page, PHP doit inclure toutes les librairies nécessaires à l'exécution du code. Dès qu'on utilise un nouveau composant dans le projet, on doit retourner au fichier bootstrap pour ajouter la librairie à la liste de chargement.
require_once('Zend/Cache.php');
require_once('Zend/Config.php');
require_once('Zend/Date.php');
require_once('Zend/Db.php');
require_once('Zend/Dom/Query.php');
require_once('Zend/Locale.php');
require_once('Zend/Measure/Binary.php');
...
Comme une page n'utilise pas tous les objets, pourquoi ne pas laisser autoload décider quelles librairies charger, au moment de l'instanciation ? Ceci peut se faire par la fonction __autoload de PHP ou encore par la classe Autoloader du Zend Framework. Étant donné que les noms sont uniformisés (remarquez que Zend_Dom_Query est placé dans Zend/Dom/Query.php), on peut tirer avantage de cette classe pour simplifier la structure du projet. Le mécanisme d'autoload est légèrement moins performant mais dans la balance, on y gagne probablement si le script PHP n'a pas besoin de toutes les classes.
Ce qui veut dire que toute la série de require_once() ci-dessus peut être remplacée par deux lignes de code :
require_once('Zend/Loader/Autoloader.php');Avec ça, dès qu'un objet du Zend Framework est créé, ZendLoader charge le fichier sur demande. Fini les longues listes de fichiers inclus.
$autoloader = Zend_Loader_Autoloader::getInstance();
Notez qu'on peut aussi combiner les deux approches :
- inclure systématiquement toutes les librairies critiques à l'application web
- laisser Zend_Loader charger les librairies secondaires ou celles qu'on aurait pu avoir tendance à oublier
Sur mon PC, j'ai installé Ubuntu 9.04 (Jaunty Jackalope) en dual boot avec Windows XP. Comme matériel, je possède une souris Microsoft Comfort Optical Mouse 3000, une souris bon marché assez standard, si ce n'est que du bouton rouge sur le côté gauche (pouce) que j'ai l'habitude de configurer sous Windows pour permettre le retour à la page précédente dans Firefox.
Sur Linux, ma souris fonctionne correctement, sauf pour le bouton rouge. Pour le configurer, je devais d'abord vérifier comment les boutons étaient définis par le système.
Avec un terminal, j'ai demandé à xmodmap d'imprimer la liste associative des codes (de 1 à 32) associés aux boutons physiques du pointeur (souris).
xmodmap -pp
Ensuite, toujours avec le terminal, j'ai lancé le programme xev qui affiche les événements lorsqu'on clique dans la boîte graphique.
xev
En cliquant sur les boutons de la souris (en prenant soin de ne pas la bouger car je ne veux pas voir les événements reliés aux déplacements), je vois des informations, dont ButtonRelease event, KeyRelease event... :
Gauche : button 1
Click sur scrollwheel : button 2
Scroll haut : button 4
Scroll bas : button 5
Droite : button 3
Bouton de coté (rouge): button 9
En général, il semblerait que les boutons de côté (Back / Forward) soient placés respectivement aux index 8 et 9. Comme je n'ai qu'un seul bouton, mon hypothèse était que le bouton de pouce aurait été configuré automatiquement à 9 au moment de l'installation. J'ai donc tenté d'inverser la position des boutons pour que le rouge soit associé à 8.
Toujours dans un terminal :
xmodmap -e "pointer = 1 2 3 4 5 6 7 9 8"
À partir de ce moment, j'étais capable d'utiliser le bouton de pouce pour retourner à la page précédente dans Firefox. Cependant, dès la session suivante, le système perdait son mapping. J'ai lu que beaucoup d'utilisateurs effectuaient des configurations par le fichier xorg.conf (InputDevice section) mais pour mon problème très spécifique, j'ai utilisé une alternative facile. Je ne garantis pas que c'est la meilleure façon mais pour l'utilisation que j'en fait, c'était suffisant pour recharger la configuration au démarrage de ma session.
En fait, il faut d'abord déterminer si on veut que le fix soit appliqué à un seul utilisateur ou à tous. D'une façon ou d'une autre, on ajoutera une instruction au bash file qui sera exécuté au démarrage.
Appliquer à un seul utilisateur
On trouvera dans /home/[USER] un fichier caché nommé .profile (avec un point devant). On peut le voir en listant les fichiers avec ls -a. Il contient des instructions à exécuter spécifiques au profil dans lequel il se trouve ([USER] est votre nom d'utilisateur).
sudo nano /home/[USER]/.profile
Ajoutez la ligne suivante à l'intérieur :
xmodmap -e "pointer = 1 2 3 4 5 6 7 9 8"
Appliquer à tous les utilisateurs
Comme plusieurs utilisateurs peuvent utiliser le même ordinateur (donc le même matériel), ça peut être plus simple d'appliquer la correction pour tout le monde.
Il suffit d'ajouter la même ligne xmodmap, mais dans un fichier différent. Avant de charger .profile, le système charge un fichier de caractéristiques communes à tous les utilisateurs : /etc/profile.
sudo nano /etc/profile
Redémarrez la session et tout devrait bien marcher. xev pourra vous confirmer que le mapping est bien retenu.
Cette dernière façon a aussi l'avantage que les futurs utilisateurs à être créés bénéficieront de la correction.
Aucun homme ne peut espérer atteindre la sagesse tant qu'il n'a pas réalisé combien son esprit est superficiel, ignorant et obscurci par les préjugés.
Vous savez déjà que j'avais construit un jukebox touchscreen avec un vieux PC et un écran tactile ELO. Cette semaine, j'ai reçu un courriel de Silverjuke annonçant la sortie d'une extension supportant Last.fm.
J'ai profité de l'occasion pour appliquer la mise à jour à la version 2.74 et ça m'a fait penser que ça serait une bonne idée de partager avec vous un petit truc : comment faire en sorte de lancer Silverjuke en mode plein écran au démarrage de Windows, communément appellé le mode "kiosk".
En temps normal, lorsque l'application est déjà ouverte, on peut entrer en mode kiosque en appuyant sur la touche F11. L'écran des préférences apparaît pour s'assurer que vous avez choisit une option qui permet de sortir facilement du mode plein écran. Il faut ensuite cliquer sur le bouton "Démarrer".
Pour automatiser cette option au lancement de Silverjuke, il n'y a pas de case à cocher dans le GUI (Graphical User Interface). Il faut l'activer par l'invite de commande en ajoutant un paramètre de lancement : --kiosk
La façon la plus simple de forcer l'application à se lancer en mode plein écran consiste à utiliser un raccourci :
- Créez un raccourci de l'exécutable ou utilisez celui dans Start / Programs / Silverjuke
- Cliquez avec le bouton droit de la souris sur l'icône et choisissez Properties
- Sous l'onglet Shortcut, rendez-vous dans la case Target
- Si vous avez fait l'installation par défaut, vous devriez voir un chemin du type "C:\Program Files\Silverjuke\Silverjuke.exe"
- Remplacez la ligne par la suivante en prenant soin d'ajouter --kiosk à la fin : "C:\Program Files\Silverjuke\Silverjuke.exe" --kiosk
- Cliquez OK pour enregistrer les changements
Il ne restera qu'à lancer le programme au démarage de Windows. Vous pouvez simplement placer le raccourci dans Start / Programs / Startup ou encore, si vous devez respecter une séquence de chargement spéciale pour votre système, je vous suggère de reproduire ce que j'ai fait et de déléguer la tâche à un fichier .bat.
Il suffit de créer un fichier texte et d'y inclure les deux lignes suivantes :
CD C:\Program Files\Silverjuke\
START Silverjuke.exe --kiosk
La première commande CD permet de changer de répertoire pour se rendre à l'endroit où Silverjuke.exe se trouve. La seconde ligne démarre le programme.
Finalement, renommez l'extension .bat et placez le dans le répertoire Startup.
Les employés de l'équipe de Windows Live Messenger (Microsoft) ont lâché leur fou en tournant une vidéo humoristique avec la mascotte de MSN (le bonhomme vert). Tout ça pour souligner le 10ème anniversaire de la populaire application de messagerie.
On n'est pas habitué à ce genre de promotion de leur part, mais on doit avouer que cette fois-ci, elle est très réussie.
Triste nouvelle ce matin, on apprend le décès de l'auteure Nelly Arcan. Dans son roman "Folle" publié en 2004, elle écrivait :
Si on en veut aux gens qui se suicident, c'est parce qu'ils ont toujours le dernier mot.
J'ai lu ceci et je ne pensais pas que c'était vrai jusqu'à ce que je vérifie. On peut retrouver le numéro de série de Windows XP sans même posséder l'étiquette indiquant la licence.
Si vous êtes en possession du CD d'installation, vous pourrez le récupérer en suivant ces quelques étapes simples :
- Insérer le CD de Windows dans le lecteur
- Ouvrez l'explorateur de fichiers (Touche Windows+E ou click droit sur l'icône du lecteur / Explore)
- Sélectionnez le dossier i386
- Cherchez pour le fichier UNATTEND.txt et ouvrez le
- La dernière ligne contient le numéro
Je soulève la question suivante : si on peut le récupérer aussi facilement, est-ce que ça veut dire qu'on peut aller dans n'importe quelle boutique qui expose les mini-PC en démonstration (Future Shop, Best Buy, etc), ouvrir le fichier et copier le numéro de série ?
Voici un problème d'intégration JavaScript et HTML appliqué sur le formulaire suivant :
<form id="myForm" action="page.php" method="post">Est-ce que tout est conforme jusqu'à maintenant ? Voici la suite, où le code JavaScript vous mettra sur la piste du problème. Au besoin, copiez le et faites le exécuter pour le constater. À noter que l'utilisation d'un framework comme jQuery ou Prototype (comme dans ce cas-ci) n'a aucune incidence sur le comportement.
<input type="button" id="submit" name="btnSubmit" value="OK" />
</form>
document.observe('dom:loaded', onLoad);Au moment de cliquer sur le bouton, on voit apparaître l'erreur suivante (utilisez Firefox et Firebug) :
function onLoad(){
Event.observe('submit', 'click', onClick);
}
function onClick(){
$('myForm').submit();
}
$("myForm").submit is not a function
Et pourtant, on sait tous que c'est faux. La ligne de code pourrait normalement être traduite par document.getElementById('myForm').submit() et ça serait supposé fonctionner.
Alors, quelle est la cause de l'erreur ? Croyez le ou non, si par malheur un élément du formulaire possède une propriété ID portant la valeur "submit", l'engin JS trouvera cette propriété plutôt que d'appeler la fonction du même nom. Donc il suffit de renommer l'ID autrement.
Et ce comportement peut arriver sur n'importe quelle balise INPUT, SELECT, FIELDSET, etc se trouvant entre <form></form>.
C'est donc une très mauvaise idée d'utiliser comme ID un mot clé réservé. Mon conseil serait de toujours préfixer les identificateurs uniques de façon à utiliser une nomenclature qui permettra de bien distinguer les éléments de la page.
J'ai finalement renoncé à acheter un eBook reader (Amazon Kindle, Kindle DX ou Sony Reader). D'abord parce que l'appareil est encore trop cher. Ensuite parce que j'aurais beau vouloir être écolo en économisant du papier, j'ai du mal à accepter l'argument quand la copie électronique se détaille presque le même prix qu'un format imprimé. Sans compter les autres points soulevés dans l'article Les problèmes de jelis.ca du bloggeur P.M.Lozeau.
Le format du fichier m'agace aussi. Plusieurs lecteurs électroniques nécessitent que les livres soient préalablement convertis pour être supportés par l'appareil. La dernière génération possède maintenant la capacité de supporter les PDF en format natif, mais au prix demandé, je préfère encore les lire sur mon portable (la dimension d'un netbook est parfaite, si ce n'est que pour la charge de la batterie...).
Avec les années, j'ai accumulé une collection intéressante de livres de référence reliés au domaine de l'informatique et de la programmation. L'avantage majeur étant de pouvoir effectuer des recherches textuelles sur le contenu de l'ensemble des fichiers. L'appareil dont je rêvais aurait permis de charger la bibliothèque électronique que je possède, sans risque de se faire effacer par le service du vendeur (Amazon?), sans avoir à les convertir, sans protection électronique, etc. J'avais essayé d'en charger quelque uns sur mon iPod Touch mais on s'arrache les yeux à essayer de les lire. C'est pour ça qu'un netbook demeure jusqu'à preuve du contraire, l'alternative de choix : sans contrainte, léger, multifonctionnel et compatible avec n'importe quel format.
Pour trouver les eBooks, j'avais plusieurs cordes à mon arc mais le truc le plus sûr pour les trouver était simple et sans mauvaise surprise. Google offre depuis longtemps une fonctionnalité qui permet de lancer une recherche dans les index qui, au lieu de fouiller dans le contenu, vérifie uniquement les mots clés se trouvant dans l'URL.
Il suffit d'inscrire dans la case de recherche :
allinurl:postgresql pdf
Ou de façon plus spécifique :
allinurl:postgresql filetype:pdf
Retirer les résultats provenant d'un domaine spécifique (le symbole - est la négation d'une propriété) :
allinurl:postgresql filetype:pdf -inurl:postgresql.org
La magie dans tout ça est qu'il n'est pas nécessaire d'installer aucun torrent, p2p ou autre pour les obtenir. Malheureusement, en raison des droits d'auteur, Google a retiré de son index beaucoup de ces fichiers. Mais en fouillant un peu, c'est facile d'en dénicher cachés dans RapidShare ou autre service de téléchargement web. Malgré tout, il reste que cette astuce est pratique pour chercher n'importe quelle sorte de fichier ou URL.
Sinon, pour vous aider à faire vos propres recherches en toute légalité, je vous suggère deux autres sources qui vous donnera accès à une source infinie d'information :
Dans les derniers mois, j'avais suggéré deux engins de coloration syntaxique : GeSHi (Generic Syntax Highlighter) qui s'exécute côté serveur et syntaxhighlighter, qui est 100% JavaScript.
Aujourd'hui, dans le cadre d'une présentation de code par un programmeur, j'ai découvert une autre méthode pour colorer du code PHP. C'est presque trop simple car c'est une fonction built-in. Elle permet de reconnaître et d'orner les balises HTML, les commentaires, les mots clés ainsi que les chaînes de caractères selon un jeu de couleurs par défaut.
Avec highlight_file(), on peut fournir comme paramètre n'importe quel chemin de fichier PHP fonctionnel. Il le lira, lui appliquera les styles et enverra le résultat vers la sortie standard (le fureteur). De son côté, highlight_string() fait la même chose mais on doit lui fournir une variable contenant le code. Pour que ça fonctionne correctement, n'oubliez pas qu'il doit trouver les <?php ?>. Dans chaque cas, un deuxième paramètre optionnel (booléen) permet de retourner le code plutôt que de l'afficher.
Si les couleurs par défaut (orange, vert, bleu et rouge) vous déplaisent, vous pouvez en tout temps les redéfinir dans php.ini ou avec ini_set().
php.ini
highlight.string = #DD0000
highlight.comment = #FF9900
highlight.keyword = #007700
highlight.bg = #FFFFFF
highlight.default = #0000BB
highlight.html = #000000
ini_set()
echo ini_set('highlight.default', '#657253');Résultat :
echo ini_set('highlight.string', '#FFFFFF') ;
echo ini_set('highlight.keyword', '#C9E3A6; font-weight: bold;');
echo ini_set('highlight.comment', '#BBBBBB');
highlight_file('Zend/Loader.php');
Chez Canada 411, on emploie soit des dyslexiques, soit des rédacteurs ayant les mains pleines de pouces.
Vu dans la section recherche inversée par numéro de téléphone :
- Veuillaz entrer...
- ... des caractètres ...
Merci, bonsoir.
En faisant du ménage cet après-midi, j'ai déniché deux tours de CD/DVD que j'ai parcouru attentivement afin de prendre une décision sans appel : garder ou jeter ?
Parmi la centaine de disques, deux ont retenus mon attention :
- Internet Explorer 2.0 includes Tutorial (!!!)
- Netscape 3
Le premier date d'environ 1995, lors de la sortie de Windows 95. Le second, vers 1996 alors qu'il faisait encore parti de la série des Netscape Navigator.
Le verdict : je garde ces deux là pour ma collection personnelle. Ce sont vraiment les deux seuls qui pouvaient avoir une quelconque valeur (sentimentale ou historique ?). Pour les autres, qu'est-ce qu'on peut faire ? Poubelle ou recyclage ?
Tous ces CD n'ont plus aucune valeur de revente ou d'utilité. Ce sont pour la plupart des démos de jeux, des très vieilles versions d'applications, une bonne dizaine d'essais gratuits d'un mois pour AOL (que je recevais involontairement par la poste pendant un certain temps), samplers de musique, etc.
Après vérification, la collecte sélective de Montréal n'accepte toujours pas ce type de déchet. Il faut se tourner vers des spécialistes.
En effectuant des recherches, j'ai lu un article concernant un reportage sur le recyclage de CD sur le site web de l'émission La Vie en Vert (Télé-Québec). Il existe une entreprise de Pointe-Claire (Québec) nommée Targray qui offre le service de recyclage.
On y apprend aussi que Future Shop et Best Buy ont mis sur pied des programmes pour récupérer les CD de données, de même que les piles usées et un certain nombre d'appareils électroniques.
Sinon, une autre source d'information utile a été un article publié sur Brouehaha en 2007. Saviez-vous que les disques peuvent être recyclés pour récupérer le polycarbonate qui sert à fabriquer des casques de vélo ?
Dans les derniers mois, j'ai travaillé principalement sur un projet web ambitieux, avec beaucoup de fichiers, de classes, etc. Sans méthodologie de travail et cahier de production, ça pouvait devenir difficile de se rappeler toutes les nouvelles demandes, améliorations souhaitées, corrections et autres.
Comme certains autres éditeur, NetBeans IDE scrute le code du projet pour permettre la fonctionnalité d'auto-complétion sur les noms de variables, fonctions et classes. Du même coup, il recherche dans les commentaires les occurences par défaut de @todo, TODO, FIXME, XXX, PENDING et <<<<<<<, ce dernier étant relié au marqueur de conflit de SVN. Ce qui permet d'identifier les zones où du travail reste à faire, le code à paufiner ou à fixer ainsi que les omissions potentielles qu'on aurait pu oublier dans l'ensemble du projet. Avant de découvrir que NetBeans possédait une telle capacité, j'avais l'habitude de mettre un tag personnel (mon nom par exemple) que je pouvais retrouver avec effectuant une recherche dans les fichiers sources du projet. Du coup, l'éditeur offre une méthode beaucoup plus efficace qui s'avère profitable au niveau de la clareté et de la productivité. Il suffit de parsemer son code source de commentaires comme ceux ci-dessous : // @todo : simplifier cette fonction // TODO : remplacer par un composant ZF /* FIXME : bug division par zéro */ // PENDING : en attente du code du stagiaire // XXX : hum ?
Ensuite, pour faire apparaître le panneau qui liste les tâches à faire, on y accédera par le menu Window / Tasks ou encore par le raccourci CTRL+6.
Si vous travaillez avec une équipe de développeurs, vous voudrez peut-être créer vos propres identificateurs pour reconnaître à qui s'adresse la correction demandée. Une fois dans SVN, si tout le monde prend l'habitude de consulter la liste des tâches, ils verront le travail qui leur est assigné. En un simple click sur la tâche, le programmeur sera amené à l'ancre où l'identificateur a été détecté.
Pour en ajouter, rendez-vous au menu Tools / Options / Miscellaneous / Tasks. Ajoutez un nouvel élément, par exemple : @code18. Sinon, vous pouvez tout simplement indiquer de façon plus générique @todo code18.
À l'aide des icônes se trouvant à gauche de la liste, vous pourrez filtrer les tâches selon le fichier courant, le projet actuel et ses dépendances ou tous les projets ouverts.
Un dernier conseil : utilisez ces tags avec modération. C'est toujours mieux de prendre l'habitude de corriger les bugs à mesure qu'ils sont découverts plutôt que d'attendre à la fin du projet.
Avez-vous déjà remarqué qu'on peut reconnaître les nombres qui se divisent par 9 à la caractéristique que la somme de tous les chiffres du nombre donneront toujours 9 ?
Par exemple :
9 x 1 = 9
9 x 2 = 18 (1+8 = 9)
9 x 3 = 27 (2+7 = 9)
9 x 4 = 36 (3+6 = 9)
...
9 x 12 = 108 (1+0+8 = 9)
Ce qui nous permet de déduire facilement qu'un nombre élevé comme 5274 est un multiple de 9 :
5+2+7+4 = 18 (1+8 = 9)
Ou encore 46019565 l'est aussi :
4+6+0+1+9+5+6+5 (36 où 3+6 = 9)
Ça m'arrive souvent de venir brancher des éléments dynamiques à l'intérieur d'un gabarit HTML. D'autres fois, c'est plutôt le contraire : je veux pouvoir extraire des parties du DOM pour les utiliser dans un contexte de programmation dynamique.
Par exemple en récupérant une portion d'une page locale ou distante, avec fopen(), file_get_contents() ou CUrl. De façon plus concrète, disons que j'ai une page web où je voudrais prélever le titre du document, c'est-à-dire le texte se trouvant entre les balises <title></title>, je peux utiliser un moyen facile d'y arriver, sans utiliser une expression régulière. Il s'agit de l'objet Zend_Dom_Query qui fait partie du Zend Framework.
En fait, il faudra se familiariser avec quelques notions :
require_once('Zend/Dom/Query.php');Deuxièmement, il faut lire le fichier modèle. Dès qu'on possède une variable qui contient le code HTML, on peut procéder à l'extraction.
$html = file_get_contents('template.php');Comme l'objet $dom contient maintenant le code HTML, on est prêt à le questionner. Ceci peut se faire par requête XPath ou par sélecteur CSS. Dans mon cas, la balise "title" ne possède pas de classe CSS donc je privilégerai le XPath. Le XPath permet de traverser un document structuré en XML ou XHTML et de lui demander d'obtenir la liste des nodes se trouvant sous un élément.
$dom = new Zend_Dom_Query($html);
Le titre étant à la racine (//) du document, on y accédera par : //title
$listDomElements = $dom->queryXpath('//title');Si vous faites imprimer le résultat, vous verrez apparaître quelque chose qui ressemble à ceci :
Zend_Dom_Query_Result Object ( [_count:protected] => [_cssQuery:protected] => [_document:protected] => DOMDocument Object ( ) [_nodeList:protected] => DOMNodeList Object ( ) [_position:protected] => 0 [_xpath:protected] => [_xpathQuery:protected] => //title )
Il s'agit d'une structure Zend_Dom_Query_Result qui contient un DomElement de PHP. Ce n'est pas un array mais comme l'objet implémente les interfaces Countable, Iterator, on peut appeler foreach() sur le jeu de résultats.
echo 'Nombre de nodes trouvés : ' . count($result);Si on préférerait obtenir une référence sur tous les DIV à l'intérieur du BODY (toujours en XPath) :
foreach($result as $node){
// textContent est une propriété de DOMElement
echo $node->textContent;
}
$result = $dom->queryXpath('//body/div');Ou si le document contient plusieurs listes (UL) et qu'on veut extraire les LI de celle qui possède la classe CSS "main" :
$result = $dom->query('.main li');Notez ici la différence : on utilise query() pour une requête par sélecteur CSS plutôt que queryXpath().
Enfin, si ce qui vous intéresse n'est pas le contenu du node mais ses attributs (ou si une vérification s'impose), DOMElement permettra d'en connaître davantage, par exemple pour détecter s'il possède un ID à la bonne valeur :
if( $node->hasAttribute('id') && $node->getAttribute('id') == 'liDefault' ){
echo "c'est celui que je cherche";
}
Avec les premiers matchs de la pré-saison de hockey ayant eu lieu cette semaine, c'est là qu'on peut voir les talents émerger de la masse.
L'humoriste Louis-José Houde a récemment mis sur la "map" le joueur "L'Aveuglette", reconnu pour ses réceptions de passes laborieuses. Aujourd'hui, je vous présente un héros obscur qui risque de faire sa marque dans la NHL (en particulier chez les Blues) : Unknown.
Hier soir, la jeune recrue a eu le privilège d'ouvrir la marque dans un match opposant le Wild du Minnesota contre les Blues de St-Louis, comme en témoigne la marque finale ci-dessous :
Un choix logique et payant pour votre prochain pool de hockey.
Un fidèle lecteur m'a fait parvenir un imprimé d'écran provenant de pgAdmin III pour PostgreSQL où l'astuce du jour affichait :
Did you know... The answer to the question of Life, the Universe and Everything is 42.
Exactement, 42. Selon le livre The Hitchhiker's Guide to the Galaxy (Le Guide du voyageur galactique) de Douglas Adams, il n'a suffit que de 7,5 millions d'années à un super-ordinateur pour calculer la réponse à la question que tous se posaient depuis la nuit des temps.
Google
On se rappellera aussi que le moteur de recherche Google avait été un des premiers à créer ce type d'easter egg en utilisant son outil de calculatrice pour fournir la réponse à cette question philosophique. Il suffit d'entrer (aucune ponctuation) : the answer to life the universe and everything
Certains diront qu'elle est vieille. D'autres souligneront que la blague est tellement bonne, qu'elle a été reprise partout. La preuve, Bing et Wolfram Alpha ont trouvé le moyen de l'intégrer eux aussi dans leurs résultats. Probablement à cause du facteur "cool".
Bing (Microsoft)
Wolfram Alpha
Maintenant que vous aussi connaissez le secret (et que vous pouvez prétendre à devenir une divinité parce que vous avez réponse à tout), vous comprendrez la référence du t-shirt 42 Ringer Shirt en vente sur ThinkGeek.
Aujourd'hui, je fouillais pour trouver un moyen simple de traiter un fichier CSV en PHP. Mon idée était d'inviter le visiteur à télécharger son fichier par un formulaire, à choisir quelques options et à importer le contenu dans une base de données en cliquant sur un bouton. En cherchant une base solide pour manipuler ce type de structure, j'ai découvert l'objet built-in SplFileObject de la SPL (Standard PHP Library).
Oui, j'aurais certainement pu ouvrir le fichier de façon standard, le lire ligne par ligne, exclure celles vides, séparer les enregistrements avec split(), etc. Mais à quoi bon si SplFileObject le fait pour moi ? En plus, comme c'est une classe spécialisée pour solutionner ce type de pattern, on peut l'utiliser tel quel ou hériter notre objet de celui-ci.
Pour faire ça simple, prenons un fichier CSV séparé par tabulations :
echantillon.csv
a1 a2 a3 a4 a5Lecture du fichier
b1 b2 b3 b4 b5
c1 c2 c3 c4 c5
$fo = new SplFileObject('files/echantillon.csv');Notez ici que le caractère de tabulation doit être inscrit entre guillemets pour que ça fonctionne. Ensuite, définissez les flags d'options :
# définition du caractère séparateur de colonnes
$fo->setCsvControl("\t");
$options = SplFileObject::READ_CSV + SplFileObject::DROP_NEW_LINE + SplFileObject::SKIP_EMPTY;Utilisé seul, SplFileObject::READ_CSV lira toutes les lignes mais les transformera en array indexé (selon le caractère séparateur spécifié) pour manipuler les données plus facilement. S'il y a des lignes vides (comme la 3ème), elles seront incluses dans le tableau.
Pour les exclure, on additionnera la combinaison des flags SplFileObject::DROP_NEW_LINE et SplFileObject::SKIP_EMPTY.
$fo->setFlags($options);Enfin, on lira le fichier ligne par ligne :
foreach( $fo as $line ){Avec ce simple bout de code, ça devient facile d'imaginer un formulaire plus flexible qui comprend :
# attention, le offset pourrait être vide!
# on s'assure qu'il y a bien 5 colonnes
if( count($line) == 5 ){
list($col1, $col2, $col3, $col4, $col5) = $line;
# utiliser les variables
# ...
}
else{
echo 'Ligne incomplète';
}
# sinon, on y accède par l'index
# echo $line[0];
}
- input file pour fournir le fichier
- choix du caractère séparateur (select box)
- radio button pour indiquer si le fichier comprend le nom des colonnes en entête
Avec ma copine, nous sommes allés visiter une de ses amies pour célébrer son anniversaire. Durant la soirée, son copain, sachant que je travaille dans le domaine de l'informatique, s'est mis à me raconter et m'expliquer comment il avait usé d'ingéniosité pour dessiner les schémas de sa future maison en utilisant un tableur Excel. Il avait redimensionné toutes les cellules pour créer des carrés d'une superficie identique (je crois que c'était à l'échelle de 1 x 1 pied) et il utilisait l'épaisseur des bordures qu'il mettait en gras pour créer les divisions de murs intérieurs et extérieurs, le mobilier, etc.
À mon grand étonnement, il avait créé une multitude de plans, tous plus complexes les uns des autres. Certains illustraient des maisons plein pied, d'autres à étages, les aménagements possibles du sous-sol, de la cour arrière, du paysagement, piscine, cabanon, etc.
En tout cas, j'étais impressionné. Passer des heures interminables à mettre ses efforts pour un résultat si simpliste, je lui lève mon chapeau! Il faut certainement être très créatif pour utiliser Excel dans ce sens. Mais n'est-ce pas là la preuve qu'il faut disposer des bons outils pour travailler efficacement ? Ça me laisse l'impression que c'est un peu comme si je donnais une cuillère à un charpentier et espérer qu'il soit productif...
Bien entendu, il existe des manières alternatives plus simples de créer des plans amateurs de qualité. Par exemple, je pense à l'application open source gratuite Sweet Home 3D. En quelques minutes, à l'aide du drag & drop, j'ai pu créer une pièce complète avec les dimensions approximatives prises chez moi, en plan 2D qui se transforme automatiquement en version 3 dimensions.
Suite à la modélisation, on peut exporter le plan en mode photo, avec un rendu très léché, où un jeu d'ombres et lumières donne une image très réaliste. Le résultat est impressionnant comme en témoigne l'exemple suivant :
Il ne fait pas de doute que je lui enverrai le lien de ce logiciel, surtout qu'il est disponible pour Windows, Mac OS X, Linux et Solaris. Pour ma part, j'ai bien l'intention de m'amuser avec Sweet Home 3D pour compléter le plan de ma demeure.
D'ailleurs, ça me fait penser qu'il y a plusieurs années, je m'étais procuré une application commerciale similaire nommée Home Design 3D (version 3.0), par Expert Software (~ 1995), qui tenait sur une disquette et nécessitait au minimum Windows 3.1. Je n'ai aucun souvenir du prix, mais de nos jours, il est judicieux de vérifier d'abord s'il y a un équivalent libre de disponible.
Justement, avez-vous eu connaissance du mouvement BadVista ? Une alternative est toujours à votre disposition, la décision vous revient.
La civilisation progresse par l'extension du nombre d'opérations importantes que nous pouvons accomplir sans avoir à y penser.
Suite à ma série d'articles de cette semaine (clé USB, netbook, partitions, etc), une simple question se pose : comment créer un ISO d'un disque (CD / DVD) qu'on possède déjà plutôt que d'en télécharger un (FTP, Torrent, autre) ?
Sous Linux, c'est simple (exemple avec Ubuntu 9.04), il suffit d'utiliser un invite de commande et de lancer dd (Dataset Definition), le programme qui permet de copier et convertir des données brutes (n'oubliez pas de monter le disque si le OS ne le fait pas automatiquement pour vous).
dd if=/dev/cdrom of=/tmp/disk.iso
Où :
- if = input file
- of = output file
Avec Windows, utilisez un des interfaces graphiques suivant :
- Nero, une application commerciale, possède une option pour gérer les fichiers ISO
- Format Factory, un gratuiciel sponsorisé qui offre la conversion de DVD/CD à ISO/CSO
Cette semaine, je programmais dans une base de données PostgreSQL quand je me suis rendu compte que la nature d'un champ d'une table avait changé par rapport à ce qui avait été prévu initialement. Ni son nom ni son type n'avaient été changés, ce qui portait à confusion.
Pour pallier à ce manquement, j'ai décidé de faire une recherche dans le code source ainsi que dans la base de données pour les remplacer par quelque chose de plus approprié.
Après avoir cherché dans le DDL et fait les remplacements, j'ai utilisé une requête SQL qui appelle les tables systèmes et qui liste le nom de la table suivi du nom du champ trouvé (notez que j'utilise un ILIKE) :
SELECT tbl.relname, col.attnameJe partage ce petit truc avec vous, en espérant que ça servira à quelqu'un.
FROM pg_attribute as col
INNER JOIN pg_class as tbl ON col.attrelid = tbl.oid
WHERE col.attname ILIKE '%nom_de_colonne%'
ORDER BY tbl.relname
Redimensionner une partition existante sans perdre de données
Hier, j'ai préparé ma clé USB pour installer Ubuntu 9.04 sur mon netbook Acer Aspire One. Le problème, c'est qu'au moment de l'achat, Windows XP était pré-installé et prenait toute la place. Toute ? Pas tout à fait. Environ 2 Go était inutilisés à la fin du disque, soit trop peu à mon goût pour installer Linux en dual-boot. Le reste de l'espace était divisé entre deux partitions, une première de 7 Go servant au recovery pour réinitialiser le mini-portable à sa configuration d'origine, la seconde de 140 Go pour Windows.
Il faut savoir qu'un disque dur d'un volume de 160 Go vendu sur le commerce en équivaut réellement à environ 149 Go (comme je l'ai déjà expliqué dans un autre article, à cause du calcul par la notation internationale). Donc comment puis-je installer Linux en disposant de suffisamment d'espace sur le disque, sans le remplacer ni le formater et tout réinstaller à nouveau ?
Avec la procédure expliquée hier, je peux connecter ma clé USB et booter Ubuntu Live sans même l'installer sur le disque (c'est plus tard qu'on décide de l'installation). Si votre ordinateur portatif contient un lecteur CD, vous pourrez aussi utiliser le CD/DVD d'installation pour arriver au même résultat.
Au chargement, une nouvelle option apparaît au menu System / Administration / Partition Editor. Il s'agit de l'application GParted qui permet de redimensionner une partition existante sans perdre de données (faites quand même une copie de sauvegarde de vos fichiers importants, juste au cas où).
Avec GParted, je décide de conserver intacte la partition de recovery mais de réduire à 100 Go celle de Windows pour laisser 40 Go pour Linux.
Pour le moment, je me contenterai de redimensionner la partition Windows puisque je pourrai créer les nouvelles partitions nécessaires à Ubuntu (ext3 et swap) au moment de l'installation du OS.
Dans GParted, sélectionnez la partition NTFS de Windows et cliquez sur le bouton Resize/Move. Entrez la nouvelle taille désirée (new size). Par exemple, pour 100 Go, calculez 100 * 1024 = 102400.
/dev/sda1 ntfs (7 Go)
/dev/sda2 ntfs (de 140 Go à 100 Go)
Appliquez les changements. Ceci peut prendre du temps, alors prévoyez entre 1h30 et 2h pour que le travail se fasse. Aussi, mieux vaut le brancher à la prise murale durant le processus. Au démarrage suivant de Windows, l'utilitaire "scan disk" démarre automatiquement pour vérifier la consistence des données (ne vous inquiétez pas, c'est normal).
À partir d'ici, votre netbook est prêt à héberger un second système d'exploitation et vos données sont conservées telles quelles. C'est presque magique!
En visitant le Google Store ce matin à cette adresse, je suis tombé sur cette erreur d'exécution qui s'affichait à l'écran la directive suivante :
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="err.aspx.cs" Inherits="Ecometry.Web.Impl.err" %>
Imprimé d'écran :
Voilà la preuve que même Google peut se permettre d'utiliser la technologie .NET/C# de son concurrent Microsoft. C'est vrai que c'est seulement pour la boutique, ça n'a pas la même importance que leur moteur de recherche. Et qui sait s'ils n'utilisent pas le projet Mono ?
Mise en situation : vous vous êtes procuré un netbook pré-installé avec Windows XP mais vous préféreriez pouvoir le rouler avec une distribution Linux. Le problème, c'est que le netbook en question ne possède pas de lecteur optique pour y insérer le CD-ROM d'installation...
La solution : simulez le tout grâce à une clé USB. D'abord, vous devez créer un fichier .iso du CD-ROM ou du DVD d'installation. Un ISO est tout simplement une image du disque, sous forme d'un fichier unique. Sinon, téléchargez-le sur le web, par exemple celui d'Ubuntu.
Une fois en possession de l'ISO, on peut se rendre sur SourceForge.net et télécharger UNetbootin, disponible gratuitement, tant sur Windows que Linux.
Avant de lancer le programme :
- assurez-vous que votre clé USB est branchée
- le volume de la clé est-il suffisant pour contenir l'image du disque ? (au minimum 1 Go pour un CD-ROM)
- Image du disque : ISO
- Sélectionnez le fichier .iso sur votre poste en cliquant sur le bouton "..."
- Type : Disque USB
- Disque : la lettre correspondant à votre clé USB
Cliquez OK, le processus de transfert démarrera automatiquement. Quatre étapes seront exécutées :
- Téléchargement des fichiers (optionnel, seulement si vous choisissez une version en téléchargement dans Distribution / Version)
- Extraction et copie des fichiers (vous devrez patienter plusieurs minutes, vous avez le temps d'aller vous faire un café)
- Installer le gestionnaire de démarrage
- In(s)tallation terminée, redémarrage
Il est possible que le netbook démarre normalement et que le système d'exploitation par défaut se charge. Dans ce cas, vous devrez modifier le BIOS (généralement avec la touche F2) avant le chargement de l'OS pour changer la priorité de chargement des périphériques. Placez l'ordre de façon à ce que USB-HDD précède le disque dur (la clé USB a généralement une faible priorité et devrait se retrouver vers la fin). Enregistrez les modifications.
Redémarrez l'ordinateur et profitez de l'installation de Linux sans même avoir de CD-ROM!
Une clé USB possède par défaut le système de fichiers FAT32 qui permet de stocker des fichiers d'une taille maximale de 4 Go. Comme je voulais placer sur ma clé des fichiers vidéos volumineux ainsi qu'un ISO d'installation Linux, je devais d'abord transformer le système de fichiers pour qu'il soit en NTFS.
Windows possède l'exécutable "convert", qui doit être appellé par l'invite de commande avec la syntaxe suivante :
convert lettre: /fs:ntfs
Exemple :
convert e: /fs:ntfs
Sinon, on peut télécharger l'utilitaire gratuit HP USB Disk Storage Format Tool qui permet, contrairement à Windows XP (click droit sur le volume de fichier / Format / FAT32), de formater en NTFS.
Demain, j'expliquerai comment rendre une clé USB bootable pour pouvoir installer un système d'exploitation à partir d'une clé USB, par exemple sur un Netbook qui ne possède pas de lecteur optique.
Sous Linux, pour lister le contenu d'un répertoire à partir d'un terminal, on sait qu'on doit utiliser la commande ls. Cependant, ls -l est plus pratique car elle permet de montrer plus d'informations, dont les permissions, la taille des fichiers, le propriétaire, etc.
Mais savez-vous que plusieurs distributions permettent d'appeler cette même commande en utilisant la commande ll ? En fait, il faut savoir qu'il s'agit d'une pré-configuration d'alias installée par défaut.
Pour connaître la liste des alias connus par le système d'exploitation (et pour le l'utilisateur courant), il suffit d'appeler la commande alias.
C'est là qu'on voit que ll est un alias pour ls -l --color=auto. Ce qui est une bonne chose car ça nous permet de redéfinir une commande existante pour la personnaliser avec les arguments qu'on voudrait utiliser par défaut.
Pour ajouter ou modifier un alias, on peut le faire de deux façons :
Modifier le fichier "bashrc"
Global (tous les utilisateurs) : /etc/bashrc
Root : /root/.bashrc
Un seul utilisateur (fichier caché) : /home/USER/.bashrc
Les commandes seront activées dès la prochaine session de terminal.
Commande Alias
Appeler la commande alias pour définir une nouvelle règle. L'avantage ici est que c'est actif dans la session en cours.
Ajout d'un alias :
alias nom='commande -arguments'
Exemple :
alias cls='clear'
Retirer un alias :
unalias nom
Exemple :
unalias cls
Vu aujourd'hui imprimé sur un t-shirt vendu dans une des nombreuses boutiques de souvenirs de la province de Québec :
Suggestion de jeu de mots douteux : quelle belle ANALogie... Promis, j'essaierai de faire mieux demain...
Si les gens ne croient pas que les mathématiques sont simples, c’est uniquement parce qu’ils ne réalisent pas à quel point la vie est compliquée.
Savez-vous prendre avantage du lookahead dans une expression régulière ? D'abord, qu'est-ce que c'est ? Le lookahead est un mécanisme d'assertion qui permet de regarder les caractères qui suivent pour voir s'il y a correspondance, sans toutefois les conserver dans le résultat retourné.
Par exemple, dans l'extrait de phrase suivant :
1èrement, je voudrais annoncer le gagnant du 1er prix...
Si on voulait remplacer "1er" pour qu'il devienne "1er" (avec la balise HTML SUP), on devrait utiliser une expression régulière qui vérifie s'il s'agit d'un chiffre, suivi du terme "er" et sa forme au féminin "ère".
(\d+)(er|ère)
Par contre, on voudra s'assurer que le mot est complet et qu'il ne remplace pas une partie du mot original car on ne veut pas que "1èrement" soit transformé en "1èrement". Dans les faits, on pourrait simplement utiliser le flag \b qui vérifie la limite d'un mot, mais pour les fins de mon exemple, je ferai exprès pour démontrer comment on le fait avec la technique du lookahead.
La regex avec le word boundary vérifie que la limite d'un mot est atteinte mais ne conserve pas l'espace qui suivrait.
(\d+)(er|ère)\b
Pour vérifier s'il y a un espace, on remplacera \b par \s à la fin de l'expression.
(\d+)(er|ère)\s
Le problème est qu'on veut vérifier la présence de l'espace, mais sans le conserver au moment du remplacement. C'est ici que le lookahead entre en jeu :
(\d+)(er|ère)(?=\s)
La syntaxe du lookahead est (?=regex). L'expression régulière qui suit ?= indiquera qu'il faut que ce qui s'en vient soit un "whitespace character", mais de ne pas le retenir dans la correspondance.
En PHP, les lignes suivantes feront le travail :
$regex = '/(\d+)(er|ère)(?=\s)/i';Le résultat :
$replace = '$1<sup>$2</sup>';
$sentence = '1èrement, je voudrais annoncer le gagnant du 1er prix...';
echo preg_replace($regex, $replace, $sentence);
1èrement, je voudrais annoncer le gagnant du 1<sup>er</sup> prix...
À noter qu'il existe aussi le lookahead négatif où la regex doit être fausse, qui utilise l'opérateur ?!.
D'abord paru sous forme de nouvelle dans le magazine Wired, l'auteur Douglas Coupland en a fait un roman. Il a passé plus de 5 mois à vivre à Redmond et Silicon Valley pour observer ce qui s'y passait et en apprendre davantage sur le milieu.
Cette fiction se situe entre les années 1993 et 1995 et raconte l'histoire d'un groupe d'employés de Microsoft assignés à différents projets et qui se voient l'opportunité de quitter un emploi stable et sécuritaire mais sans réelle possibilité d'avancement, pour se lancer dans l'aventure d'une start up. Ils se retrouvent donc entre amis, à la conquête de gloire et de richesse, même s'ils découvrent qu'ils ne le font pas que pour l'argent.
On suit leur quotidien, que Dan, le personnage principal, rédige dans un journal sur son PowerBook en y documentant un nombre impressionnant de références à des éléments de l'univers de la culture geek. Ils programmeront un jeu nommé Oops!, inspiré des Legos et de la modélisation par ordinateur.
L'auteur a su donner aux personnages des personnalités colorées, allant même jusqu'à décrire sans trop de compliments le seul qui soit canadien (Ontario), une fille aux allures plus que tomboy, qu'un des protagonistes rencontre en clavardant sur Internet et dont il tombe follement amoureux sans même savoir le genre de la personne qui se cache derrière le pseudonyme. Pourtant, l'auteur est lui-même originaire du Canada, de Vancouver plus précisément. Alors que nous vaut ce clin d'oeil ? Heureusement qu'il ne faut pas s'arrêter aux stéréotypes!
Lorsque j'ai lu le livre, j'ai apprécié revivre l'époque du début du web, de l'émergence et de l'effervescence de l'informatique populaire avant l'éclatement de la bulle technologique. Là-dessus, Coupland a fait du bon travail. Cependant, j'ai été déçu de la fin, précipitée, comme s'il avait avait plus ou moins su comment terminer l'histoire. Peut-être s'est-il reprit dans jPod, un autre livre du même genre, sorti 10 ans plus tard et qui a fait l'objet d'une série télé. J'y jetterai un oeil, soyez assuré!
En parcourant les pages, vous verrez deux messages codés dont j'ai pu retracer la signification grâce à Wikipedia. Aux pages 104-105, le code binaire représente une version adaptée du Rifleman's Creed (que vous avez certainement entendu dans le film Full Metal Jacket) :
I heart LiSA Computers. This is my computer. There are many like it, but this one is mine. My computer is my best friend. It is my life. I must master it, as I must master my life. Without me, my computer is useless. Without my computer, I am useless. I must use my computer true. I true. I must compute faster than my enemy who is trying to kill me. I must outcompute him before he outcomputes me. I will. Before God, I swear this creed. My computer and myself are defenders of this country. We are masters of our enemy. We are the saviours of my life. So be it until there is no enemy, but peace. Amen.
Aux pages 308-309, les consonnes apparaîssent sur la page de gauche tandis que les voyelles sont sur celle de droite. Le texte ainsi formé est tiré d'une lettre de Patty Hearst à ses parents, alors qu'elle avait été kidnappée.
Enfin, la version du livre que je me suis procuré contenait à la fin quelques pages supplémentaires présentant des informations pertinentes sur la rédaction du livre (entrevue, faits, etc). À lire si vous êtes amateurs de littérature geek.
Juste pour le plaisir de répertorier un autre easter egg, entrez sur le moteur de recherche Google le terme "ascii art" et cliquez sur le bouton de recherche.
Remarquez le changement de logo :
Voici un excellent site pour observer et apprendre différents algorithmes de tri.
Les algorithmes (insertion, selection, bubble, shell, merge, heap, quick et quick3) sont présentés avec incluant une explication de chaque type, le pseudo-code nécessaire à l'implémentation, les avantages et inconvénients, la possibilité d'observer visuellement le processus d'exécution selon le volume de données à traiter et l'ordre initial des éléments.
La page principale permet de comparer la performance de tri des mêmes données suivant les différents types.
Point intéressant à noter, le site sorting-algorithms.com est construit à l'aide de l'infrastructure de Google App Engine, qui permet de programmer en Python ou Java, avec une integration de Google Web Toolkit.
J'ai démontré récemment comment créer un service web facilement avec Zend Framework. Cet article pourra servir comme introduction à mon sujet d'aujourd'hui puisque j'expliquerai comment protéger l'accès à un service web en ajoutant une authentification HTTP.
Vous aurez besoin :
- Zend Framework
- un service web
- fichiers .htaccess et .htpasswd
Comme l'authentification HTTP sera réalisée à l'aide de .htaccess et .htpasswd, il sera nécessaire d'indiquer quel fichier protéger dans .htaccess. Les deux actions se trouvant dans le même fichier, il sera nécessaire de les extraire et de séparer le code exitant en deux fichiers. N'oubliez pas que l'URI service.php?wsdl n'existera plus :
- serveur.php
- definition-wsdl.php
Fatal error: Uncaught exception 'SoapFault' with message 'SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://url' : failed to load external entity "http://url" ' in file
C'est parce que le fichier qui génère la définition du WSDL fait aussi la manipulation côté serveur. Par défaut, l'objet AutoDiscover utilise le script courant, sans le paramètre ?wsdl pour trouver l'objet serveur qui prendra en charge la requête ($_SERVER['SCRIPT_NAME']). Dans notre cas, on séparera le script en deux fichiers, le premier créera le wsdl, le second servira à l'objet serveur.
La différence est qu'à la déclaration d'AutoDiscover, on devra assigner à l'objet un autre URI que celui auquel il s'attend par défaut.
Fichier definition-wsdl.php
require_once('Zend/Soap/AutoDiscover.php');Si vous ne définissez pas la ligne $auto->setUri();, vous rencontrerez l'erreur suivante :
require_once('classes/MyClass.php');
$auto = new Zend_Soap_AutoDiscover();
$auto->setClass('MyClass');
// ceci est nouveau!
$auto->setUri('http://url/vers/server.php');
$auto->handle();
Fatal error: Uncaught exception 'SoapFault' with message 'Wrong Version'...
Fichier server.php
require_once('Zend/Soap/Server.php');Fichier .htaccess
require_once('classes/myClass.php');
$server = new Zend_Soap_Server('http://url/vers/definition-wsdl.php');
$server->setClass('MyClass');
$server->handle();
Une fois les fichiers séparés, on peut ajuster .htaccess pour que seul le fichier server.php demande une authentification (plutôt que service.php).
Placez le fichier sur le serveur à la racine du répertoire du service web. Dans .htaccess, indiquez l'emplacement du fichier de mot de passe sous AuthUserFile. Ensuite, protége l'accès au fichier server.php pour qu'il nécessite une authentification.
AuthType BasicFichier .htpasswd
AuthName "Webservice"
AuthUserFile /var/www/emplacement/de/.htpasswd
<files server.php>
Require valid-user
</files>
Vous devrez créer une combinaison login / password à insérer dans .htpasswd. À ce sujet, je vous recommande la lecture de protéger l'accès d'une ressource à l'aide d'un mot de passe. Le mot de passe doit être encrypté en utilisant l'utilitaire de htpasswd.
Fichier client.php
L'objet Zend_Soap_Client permet de spécifier deux paramètres qu'on peut passer en array optionnel pour indiquer le login et le password de l'authentification HTTP lorsque nécessaire.
# $client = new Zend_Soap_Client($wsdl);À ce stade-ci, vous devriez pouvoir accéder au service web protégé. Si l'authentification ne fonctionne pas (par exemple, si vous ne passez pas $options à Zend_Soap_Client ou si les clés d'identification sont erronées), vous verrez une erreur :
# on remplacera l'appel client par ces lignes :
$options = array(
'login' => 'code18',
'password' => '81edoc'
);
$client = new Zend_Soap_Client($wsdl, $options);
$client->votreFonction();
...
Fatal error: Uncaught exception 'SoapFault' with message 'Authorization Required'