skip to main | skip to sidebar
Code 18
Manuel du savoir-faire à l'usage des geeks et des curieux
RSS
  • Accueil
  • Le web au Québec
  • Liens
  • Twitter
  • Facebook
  • À propos

vendredi 31 juillet 2009

SQL Serveur 2008 perd le mot de passe ?

Publié par Infinite Loop, à 12 h 55 0 commentaire

Avec le nouveau client SQL Server 2008 Management Studio, je me demandais pourquoi à l'ouverture (voir écran ci-dessous), il retenait parfois le nom du serveur et le mot de passe alors qu'à d'autres moments complètement aléatoires, il s'en souvenait. Pourtant, je prenais la peine de cocher la case "Remember Password" !



La solution fiable pour qu'il retienne les connexions aux serveurs est la suivante :

  • Ouvrir le menu View
  • Choisir Registered Servers
  • Une fenêtre s'ouvre intitulée "Registered Servers
  • Ouvrir le treeview Database Engine
  • Sur Local Server Groups, cliquez avec le bouton droit de la souris et choisir New Server Registration dans le menu contextuel
  • Entrez l'information
  • Enregistrez


Sinon, si on est déjà connecté au serveur et qu'on le voit dans Object Explorer :
  • Cliquez sur le bouton droit de la souris sur le nom du serveur
  • Choisir Register dans le menu contextuel
Enfin on peut passer à autre chose !


Tags: SQL Server

jeudi 30 juillet 2009

Regex greedy vs. lazy

Publié par Infinite Loop, à 17 h 34 3 commentaires

Dans le monde des expressions régulières, il existe des modificateurs qu'on surnomme "lazy" (paresseux) et "greedy" (gourmand). C'est important de savoir comment ça fonctionne car non seulement ça permet d'optimiser la performance de la correspondance, mais ça évite surtout des surprises.

Note : si vous voulez suivre ce petit tutoriel pas à pas, je vous suggère d'ouvrir une nouvelle fenêtre de regular expression tool et de sélectionner l'onglet PHP PCRE ou JavaScript, en mode "match".

Imaginez la chaîne de caractères ci-dessous :

Je mange des <strong>chips</strong> et je bois une bière

Et la regex suivante : <.+>

Effectivement, ça trouve <strong>chips</strong>.

Pourquoi est-ce que ça ne conserve pas que la première balise strong ? Parce que les opérateurs comme +, *, {} sont greedy, ce qui veut dire qu'ils ont tendance à faire correspondre la plus grande partie de la chaîne de caractères. Comme on spécifie le point et le plus, il ne s'arrête pas au premier >. Il poursuivra son chemin jusqu'à la fin (car > fait parti des caractères acceptés par le point) et il fera marche arrière pour trouver le dernier > qui équivaut à la fin du pattern spécifié.

Comment peut-on faire pour arrêter la correspondance de façon à ce qu'il en prenne le moins possible, c'est-à-dire sans backtrack ? La réponse : en utilisant un modificateur "lazy" comme le symbole "?".

En modifiant la regex initiale pour celle-ci : <.+?>, l'engin s'arrêtera aussitôt qu'il fera correspondre une section de la chaîne de caractères. Autrement dit, il en fera correspondre le moins possible.

Le résultat : seule la balise <strong> sera retenue.


Tags: Programmation

mercredi 29 juillet 2009

White & Nerdy de Weird Al Yankovic

Publié par Infinite Loop, à 19 h 30 0 commentaire

Tout geek qui se respecte se doit de connaître la chanson parodiée White & Nerdy de Weird Al Yankovic.

Quelques mots clés en gras. Pour chacun où vous vous reconnaissez, vous marquez un point. Quel est votre score ?

Weird Al Yankovic
White & Nerdy
Straight Outta Lynwood (2006)

Parodie : "Ridin' Dirty" de Chamillionaire

They see me mowin’
My front lawn
I know they’re all thinking I’m so white and nerdy
Think I’m just too white and nerdy
Think I’m just too white and nerdy
Can’t you see I’m white and nerdy?
Look at me, I’m white and nerdy
I wanna roll with
The gangstas
But so far they all think I’m too white and nerdy
Think I’m just too white and nerdy
Think I’m just too white and nerdy
I’m just too white and nerdy.
Really really white and nerdy.

First in my class here at MIT
Got skills, I’m a champion at D&D
MC Escher - that’s my favorite MC
Keep your 40, I’ll just have an Earl Grey tea
My rims never spin, to the contrary
You’ll find that they’re quite stationary
All of my action figures are cherry
Stephen Hawking’s in my library
My MySpace page is all totally pimped out
Got people beggin’ for my top eight spaces
Yo, I know pi to a thousand places
Ain’t got no grills but I still wear braces
I order all of my sandwiches with mayonnaise
I’m a whiz at Minesweeper - I could play for days
Once you see my sweet moves you’re gonna stay amazed
My fingers’ movin’ so fast I’ll set the place ablaze
There’s no killer app I haven’t run
At Pascal, well I’m number one
Do vector calculus just for fun
I ain’t got a gat but I got a soldering gun
Happy Days is my favorite theme song
I could sure kick your butt in a game of ping pong
I’ll ace any trivia quiz you bring on
I’m fluent in JavaScript as well as Klingon

They see me roll on
My Segway
I know in my heart they think I’m white and nerdy
Think I’m just too white and nerdy
Think I’m just too white and nerdy
Can’t you see I’m white and nerdy
Look at me, I’m white and nerdy
I’d like to roll with
The gangstas
Although it’s apparent I’m too white and nerdy
Think I’m just too white and nerdy
Think I’m just too white and nerdy
I’m just too white and nerdy
How’d I get so white and nerdy

I’ve been browsin’, inspectin’
X-Men comics, you know I collect ‘em
The pens in my pocket, I must protect ‘em
My ergonomic keyboard never leaves me bored
Shopping online for deals on some writable media
I edit Wikipedia
I memorized Holy Grail really well
I can recite it right now and have you ROTFLOL
I got a business doing websites
When my friends need some code, who do they call?
I do HTML for ‘em all
Even made a homepage for my dog
Yo, I got myself a fanny pack
They were havin’ a sale down at The Gap
Spend my nights with a roll of bubble wrap
Pop, pop, hope no one sees me
Gettin’ freaky
I’m nerdy in the extreme
And whiter than sour cream
I was in AV Club and Glee Club and even the Chess Team
Only question I
Ever thought was hard
Was do I like Kirk
Or do I like Picard
Spend every weekend at the Renaissance Fair
Got my name on my underwear (5 points!)

They see me strollin’
They laughin’
And rollin’ their eyes ‘cause I’m so white and nerdy
Just because I’m white and nerdy
Just because I’m white and nerdy
All because I’m white and nerdy
Holy cow, I’m white and nerdy
I wanna bowl with
The gangstas
But, oh well, it’s obvious I’m white and nerdy
Think I’m just too white and nerdy
Think I’m just too white and nerdy
I’m just too white and nerdy
Look at me, I’m white and nerdy


Tags: Musique

Bing remplacera le moteur de Yahoo!

Publié par Infinite Loop, à 10 h 47 0 commentaire

Microsoft et Yahoo! ont annoncé aujourd'hui qu'ils ont conclut une entente de 10 ans pour que Bing remplace le moteur de recherche actuel de Yahoo!. Cette stratégie leur permettra d'atteindre une part de marché totale d'environ 30%.



Commentaire impertinent... Ne trouvez-vous pas que l'interface de l'engin de recherche de Bing ressemble à une cigarette (case blanche avec embout jaune) ? S'agirait-il d'un message subliminal contradictoire avec les sportifs sur l'image d'arrière-plan ?


Tags: Curiosités

mardi 28 juillet 2009

Festival Geek de Montréal

Publié par Infinite Loop, à 21 h 52 0 commentaire

En lisant les entrées sur Yulblog (bloggeurs de Montréal), mes yeux ont croisé le titre d'un événement qui a attiré mon attention : le Festival Geek de Montréal. Ça me réjouit de voir un groupe organiser un happening original qui célèbre l'auto-dérision du cliché du geek en puissance.

Encore au stade embryonnaire, l'équipe s'active pour imaginer différentes activités. Voici quelques idées tirées de leur site web :

  • Concours de déguisement (Star Wars, Star Trek, Lord of the Ring…);
  • Sections de jeux: jeux de rôle, jeux de société, jeux de table, jeux d’ordinateur, jeux de console…;
  • Démonstrations de ce qui se fait (jeux vidéo, musique, programme, gadgets, service…) par nos Geek locaux (ouvert aux Montréalais ou au Québec);
  • Un coin pour coder (que ce soit concours ou pour aider les gens avec leur projet);
  • Un endroit pour les Gekettes (filles/femmes Geek);
  • Une parade de la fierté Geek;
  • Essais des derniers gadgets par des compagnies en TI;
  • Tables de discussions;
  • LAN party
  • Concours du plus grand geek/geekette de Montréal;
  • Un cours d’initiation à la geeketé pour les non-initiés;
  • Événement de coder, exemple: coder un jeu sur iPhone en 12h00;
  • Concours de Rock Band;
  • Enregistrement d’un Digg Nation Live à Montréal par Kevin Rose et Alex Albrecht;
  • Concours de structure en Lego;
  • et plus
Ambitieux comme projet ? C'est à suivre...


Tags: Le coin du geek, Montréal

Compter le nombre de lignes d'un fichier

Publié par Infinite Loop, à 12 h 22 1 commentaire

Pour ceux qui se posent la question comment j'ai fait pour compter le nombre de mots dans le fichier dictionnaire words de Linux dont je faisais mention hier, non, je ne suis pas encore assez fou pour les compter un par un!

J'ai préféré utiliser la commande wc (originalement Word Count) de Linux qui permet d'obtenir:

  • le nombre de lignes (-l)
  • de bytes (-c)
  • de caractères (-m)
  • de mots (-w)
  • la ligne la plus longue (-L).
À raison d'un mot par ligne :
wc -l /usr/share/dict/words

479 827 lignes.
Le compte est bon.


Tags: Linux

lundi 27 juillet 2009

Choix de mot de passe

Publié par Infinite Loop, à 20 h 55 2 commentaires

À propos des mots de passe, voici quelques conseils à suivre pour en choisir un et assurer plus de sécurité à vos comptes.

Éviter les mots de dictionnaire
Une tentative pour forcer l'accès à une zone sécurisée protégée par un nom d'utilisateur et un mot de passe consiste à procéder à ce qu'on appelle un "dictionary attack". En connaissant le username, il suffit d'essayer toutes les combinaisons possibles. Il y a de fortes chances pour que le mot de passe soit un mot du dictionnaire, un prénom, etc. Comme point de départ, il ne faut pas chercher très loin car dans les distributions Linux, des fichiers de dictionnaire sont installés par défaut. Par exemple, dans mon installation de Fedora 10, le fichiers "words" qui se trouve dans /usr/share/dict/ compte 479827 termes.

Combinaison de lettres minuscules et majuscules
Lorsque le mot de passe est sensible à la case ou s'il est encrypté, alterner des lettres minuscules et majuscules et un choix judicieux. L'encodage interne des lettres fait qu'elles n'ont pas la même valeur. Par exemple, en ASCII, un "A" possède la valeur décimale de 65 alors qu'un "a" est représenté par 97. Donc pour un mot de passe aussi simple que "vie", il ne sera pas équivalent à "VIE", "viE", "VIe", etc. Ce qui veut dire que pour un même mot, un hacker devra tenter plus de combinaisons pour réussir à le craquer.

Intégrer des chiffres et autres caractères
Réduit encore plus les chances que le mot se retrouve dans le dictionnaire en augmentant l'entropie. Le mot "code" est commun, alors que "code%18$" a peu de chance de faire parti d'une langue parlée par l'espèce humaine.

Au minimum 8 caractères
Faites l'exercice de le calculer, vous comprendrez que le nombre de combinaisons différentes à tester augmente en fonction du nombre de caractères.

Choisir un phrase ou une abréviation
Plutôt que de combiner des caractères aléatoires pour former un mot de passe, pourquoi ne pas s'inspirer d'une phrase que vous ne pourrez pas oublier en utilisant la première lettre de chaque mot : "Deux têtes valent mieux qu'une !" deviendrait : "2tv$mqu!".

Pour terminer, une dernière recommandation : changez vos mots de passe régulièrement (au minimum 1 fois par année) et évitez d'utiliser le même partout.


Tags: Sécurité

dimanche 26 juillet 2009

Compresser des archives avec PHP

Publié par Infinite Loop, à 18 h 01 0 commentaire

Mise en situation : vous programmez un site web d'achat de fichiers musicaux et vous offrez à vos clients de télécharger des mp3 individuellement ou par album. Dans le premier cas, ça ne présente pas trop de problème. Dans le cas de l'oeuvre complète, ça peut être plus convivial pour l'acheteur de pouvoir télécharger un seul fichier compressé plutôt que de répéter l'opération pour chaque chanson.

À l'aide de l'extension Zip de PECL, on peut créer dynamiquement un nouveau fichier d'archive, y intégrer les mp3, en profiter pour inclure un fichier Lisez-moi, un fichier détaillant le sommaire des achats, les droits d'auteurs ou une photo de vous.

À supposer que les fichiers mp3 soient stockés dans un répertoire privé sur le serveur et que les pièces sont classées par artiste et par album, nous pourrons lire le répertoire source et y inclure l'ensemble des mp3 qu'il contient :

$oZip = new ZipArchive();
$artist = 'Gordian Knot';
$album = 'Emergent';

$inputDirectory = "/chemin/vers/$artist/$album/";
$outputDirectory = '/tmp/';
$zipFilename = "$artist-$album.zip";

if ($oZip->open($outputDirectory.$zipFilename, ZIPARCHIVE::CREATE) === TRUE) {

foreach (glob($inputDirectory . '*.mp3') as $fullpath) {
$filename = basename($fullpath);

// créer la structure de répertoires à l'intérieur de l'archive
$oZip->addFile($fullpath, "$artist/$album/$filename");
}

$oZip->addFile('invoice.txt');
$oZip->addFile('thankyou.txt');
$oZip->addFile('summary.txt');
$oZip->addFile('copyright.txt');

$oZip->close();

# @todo
# envoyer le fichier zip en téléchargement, par FTP, par courriel, etc...

// supprimer le fichier Zip
unlink($outputDirectory.$zipFilename);
}
else {
exit("Impossible d'ouvrir $outputDirectory.$zipFilename");
}
Si votre service accepte de faire des échanges de mp3 usagés (à supposer que ça existe, au même titre que les CD et DVD), vous permettrez aux clients de déposer sur le serveur un zip contenant les mp3 et vous devrez les décompresser à la réception.
$oZip = new ZipArchive();

$pathToReceivedFile = "/path/to/deposit/Francky Vincent-Best of.zip";

$oZip->open($pathToReceivedFile);
$oZip->extractTo('D:/unzipped/');

$oZip->close();


Tags: PHP

Citation no. 40 sur l'imagination

Publié par Infinite Loop, à 09 h 47 0 commentaire

Logic will get you from A to B. Imagination will take you everywhere.

- Albert Einstein


Tags: Citations

samedi 25 juillet 2009

Algorithme de Luhn (mod10) pour cartes de crédit

Publié par Infinite Loop, à 11 h 22 1 commentaire

Ce matin, je vous présente un petit article qui intéressera les programmeurs qui développent des systèmes de paiement par carte de crédit. Naturellement, si vous n'êtes pas en mesure de vous conformer aux standards de sécurité PCI (Payment Card Industry), vous devrez vous tourner vers un sous-traitant comme PayPal, Google Checkout, Moneris, ou autre, pour déléguer la responsabilité de la saisie du numéro de carte de crédit.

Sinon, si tout est en ordre, vous pourrez utiliser les API et saisir les numéros de façon plus transparente. Lorsqu'un acheteur entrera son numéro, on pourra préalablement vérifier sa validité avant de soumettre la demande de transaction. Ceci est rendu possible à l'aide de l'algorithme de Hans Peter Luhn (maintenant du domaine public), aussi connu sous le nom de mod10. On le surnomme ainsi car il utilise l'opérateur modulo pour connaître le reste d'une division par 10 qui doit être égal à 0 pour être considéré valide. Il faut bien comprendre que ceci ne nous dira pas si la carte est réelle, en fonction ou expirée. Le checksum nous indiquera seulement si la série de chiffres ne présente pas d'erreur de saisie (chiffre manquant, inversés, etc).

Si on jete un oeil à la structure d'un numéro de carte de fictif (Visa) :

4024 0071 4630 2608

Le dernier chiffre, le 8, correspond au "check digit" qui permet de balancer le checksum.

Voici comment ça fonctionne :

1. À partir du check digit à droite, il faut multiplier par 2 la valeur de chaque chiffre suivant des bons de deux (ceux en gras)

<-- de droite à gauche
4024 0071 4630 2608

Résultat :
(8)0(4)4 (0)0(14)1 (8)6(6)0 (4)6(0)8

2. Parmi les résultats de la multiplication (nombres entre parenthèses), il faut s'assurer qu'ils sont plus bas que 10

Si ce n'est pas le cas, il faudra les forcer. Pour chaque nombre plus grand ou égal à 10, on utilisera une de ces méthodes pour obtenir le même résultat :

  • additionner chaque chiffre individuel du nombre (par exemple 14, devient 1+4 = 5)
  • soustraire 9 du nombre (14 devient 14-9 = 5)
Résultat :
(8)0(4)4 (0)0(5)1 (8)6(6)0 (4)6(0)8

3. Additionner tous les chifres, en incluant le check digit

8+0+4+4+0+0+5+1+8+6+6+0+4+6+0+8 = 60

4. mod 10

Pour ce numéro, la somme est 60. Si on le divise par 10, le modulo (le reste de la division) est 0 (60/10 = 6 ou 6,0), donc ça représente un numéro valide. Autrement, avec tout autre reste, il aura échoué le test.

Pour vous amuser à calculer le mod10, voici quelques numéros de cartes de crédit fictifs valides pour Mastercard, Visa, Amex, etc, trouvés sur le site de Graham King. Pour ceux qui penseraient pouvoir faire des achats avec ces informations, n'y pensez même pas, ça ne fonctionnera pas. ;-)


Tags: Programmation

vendredi 24 juillet 2009

Opérations sur un champ texte dans MSSQL

Publié par Infinite Loop, à 17 h 59 0 commentaire

Dans SQL Server, un champ varchar peut contenir au maximum 8000 caractères. Si on en veut stocker une plus grande quantité de données, on doit utiliser un type "text". À l'interne, ce n'est pas enregistré directement dans la row. À la place, le champ conserve uniquement un pointeur vers un autre emplacement. Ce mécanisme de BLOB (Binary Large OBject) permet de stocker jusqu'à 2 Go de données dans le champ.

Ce qu'il faut savoir avec un champ text, c'est qu'on ne peut pas le mettre à jour aussi simplement qu'un type varchar. Par exemple, pour concaténer du texte à un champ existant, on doit utiliser l'énoncé UPDATETEXT. L'idéal est de s'y prendre à l'intérieur d'une procédure stockée avec T-SQL.

Par exemple, pour ajouter une phrase :

-- modèle de table simple
CREATE TABLE tbl (
record_id INT PRIMARY KEY IDENTITY(1,1),
text_field TEXT
)

-- ajout d'un enregistrement
INSERT INTO tbl(text_field)
VALUES('Phrase 1.')

-- variable contenant le texte à ajouter
DECLARE @text_to_append varchar(1000)

-- déclaration d'un pointeur
DECLARE @ptrval binary(16)

-- initialisation de la variable
SET @text_to_append = 'Phrase 2.'

-- obtenir le pointeur
SELECT @ptrval = TEXTPTR(text_field)
FROM tbl
WHERE record_id = @id

-- pointer, offset, delete length, data
UPDATETEXT tbl.text_field @ptrval NULL 0 @text_to_append
Un petit aide mémoire :
  • Pour remplacer la valeur existante :
    offset : != null
    taille à supprimer : > 0
    données : texte à placer
  • Pour supprimer la valeur existante :
    offset : != null
    taille à supprimer : > 0
    données : vide
  • Pour insérer des nouvelles données à la suite de la valeur existante :
    offset : != null
    taille à supprimer : 0
    données : texte à ajouter


Tags: SQL Server

Plugin jQuery Uploadify 2.0.0

Publié par Infinite Loop, à 06 h 04 1 commentaire

Ce matin, la version 2.0 du plugin jQuery Uploadify est officiellement lancée.

Parmi les améliorations :

  • uniformisation des noms de fonctions file*() par uploadify*(). Par exemple, la fonction fileUpload() a été remplacée par uploadify()
  • changements majeurs dans l'implémentation (n'est plus compatible avec la façon de faire de la version 1.6.2)
  • méthode GET ou POST
  • configuration avec uploadifySettings
  • ID pour file d'attente
  • nombre de transferts simultanés
  • intégration de SWFObject
Cependant, toujours pas de traduction du composant :-(


Tags: JavaScript

jeudi 23 juillet 2009

Nouveau easter egg dans Google

Publié par Infinite Loop, à 18 h 25 0 commentaire

Je viens de jeter un coup d'oeil sur mon compte Twitter et Matt Cutts, ingénieur chez Google, a annoncé aujourd'hui un nouveau easter egg dans le populaire moteur de recherche.

En entrant le mot recursion, Google affiche un encadré proposant une recherche alternative. Évidemment, le terme proposé est "recursion".



Voyez le site Wikitionnaire pour la définition de récursion. Il y a bien juste les programmeurs pour la trouver drôle :-P


Tags: Easter Eggs

Option noConflict de jQuery

Publié par Infinite Loop, à 12 h 47 2 commentaires

Lorsque j'ai pris la décision de passer de Prototype à jQuery, j'ai eu à traverser une période d'adaptation au niveau de l'apprentissage. Mais le plus gros défi était de faire une transition en douceur dans les projets, le temps de traduire des librairies constuites initialement sur l'architecture de Prototype.

À certains moments, faute d'avoir déniché un plugin équivalent, j'ai dû à accepter le fait que je devrais, pour un certain temps, faire cohabiter les deux frameworks sur certains projets.

En temps normal, j'intégrais Prototype avec scriptaculous, une librairie d'effets visuels, en plus des scripts et classes utilitaires customs développés au cours des dernières années. Avec jQuery, certaines des fonctionnalités sont équivalentes, par exemple la notation $(). Ce qui crée évidemment un conflit car l'engin JavaScript ne sait pas si on fait référence à un ou l'autre des frameworks.

Pour contourner cette incompatibilité. jQuery offre la possibilité de résoudre le namespace en le déléguant à un autre objet. D'abord, les scripts doivent être inclus dans la page web en respectant l'ordre suivant :

<script ... src="/js/prototype.js"></script>
<script ... src="/js/scriptaculous.js"></script>
<script ... src="/js/plugin-maison-pour-prototype.js"></script>
<script ... src="/js/jquery.js"></script>
Ensuite, au début d'un bloc JavaScript, il faut invoquer la fonction noConflict().
jQuery.noConflict();
On pourra alors remplacer les appels aux fonctions jQuery :
$(document).ready();

// deviendra

jQuery(document).ready();
Encore plus court et simple, on peut assigner l'objet jQuery à une variable, ce qui nous évitera d'écrire jQuery au long devant chaque appel.
// les appels comme ceux-ci :
jQuery('#id');
jQuery.ajax();
jQuery.each();

// seront réduits à
$j = jQuery.noConflict();

$j('#id');
$j.ajax();
$j.each();
Pour un temps, inclure les deux frameworks sera un mal nécessaire en attendant la transition complète. Dans le pire des cas, ça alourdit légèrement le téléchargement initial (bien que les .js soient compressés et gzippés) mais une fois que c'est fait, les librairies reposent dans la cache du fureteur, donc ce n'est rien pour s'affoler.


Tags: JavaScript

mercredi 22 juillet 2009

Gros bon sens pour l'usage des courriels

Publié par Infinite Loop, à 21 h 41 0 commentaire

Dans l'entreprise où je travaille, on reçoit régulièrement des courriels de clients qui, lors de leurs requêtes, semblent oublier qu'il y a un humain au bout qui lira le message. Ça peut aussi arriver entre amis, mais contrairement à un milieu professionnel, on connaît un peu plus la personnalité des gens qu'on côtoie. Ces individus, par leur maladresse dans leur habileté à écrire, peuvent irritent les destinataires. Phôtes d'aurtograffe, écriture phonétique, UTILISATION DE MAJUSCULES, transfert de messages à plusieurs personnes (surtout des documents Powerpoint...), etc.

Yahoo! Mail a publié sur son blogue un guide du bon usage du mail. Un peu comme pour la conduite automobile, surtout quand ça fait longtemps qu'on a pris ses habitudes, ça vaut la peine de se replonger dans la théorie pour se rafraîchir un peu la mémoire.

Expérience personnelle

  • J'en profite pour rappeler qu'avec LOL, on comprend que vous riez, mais lololololol n'est pas plus comique. Dans le jargon de chat, LOL veut dire "Laughing out loud". Pas besoin d'en rajouter.
  • Évitez aussi de m'inclure dans vos des chaînes de lettres à envoyer à 10 de mes amis sans quoi mon fournisseur supprimera mon adresse électronique...
  • Et plus récemment, j'ai sauté ma coche quand ma belle-soeur a envoyé à tous ses contacts un canular vieux de 5 ans qui disait que le 27 août 2009, on pourrait voir la planète Mars aussi grande que la Lune. Vérifiez vos sources et usez de gros bon sens avant d'appuyer sur le bouton "Transférer"...


Tags: Saviez-vous que

mardi 21 juillet 2009

Équivalent de nslookup en PHP

Publié par Infinite Loop, à 21 h 13 0 commentaire

Ces temps-ci, je travaille sur un projet web qui m'amène à apprendre sur les notions de réseautique. À vrai dire, c'est loin d'être ma force mais je suis quand même stimulé d'avoir quelque chose de nouveau à me mettre sous la dent. Quand on apprend, les journées passent tellement vite!

Dans le cadre de mon boulot, j'ai eu à automatiser des processus qui étaient originalement exécutés manuellement à l'aide de la commande nslookup (Linux et Windows). Cette commande, comme dig, permet de faire des requêtes sur les DNS (Domain Name System) afin d'obtenir de l'information reliée aux types d'enregistrements, par exemple le MX, le A record ou le NS, pour ne nommer que ceux-là.

Dans un invite de commandes, on peut vérifier l'information d'un mail exchanger (MX) comme ceci :

nslookup -type=MX hotmail.com

Wow, 24 mx au total ?!

À titre de référence sur les requêtes que vous pouvez faire, voyez ici la liste des records types pour DNS.

Maintenant, à moi de traduire cela en PHP. Heureusement, le langage compte une librairie intéressante de fonctions réseau.

Ainsi, la fonction getmxrr() permet d'obtenir la liste des MX records associés à un domaine ainsi que leur ordre de priorité. Curieusement, on doit passer deux arrays en référence pour les obtenir séparément. On finit par les fusionner pour faciliter la manipulation. C'est pourquoi c'est plus aisé d'utiliser dns_get_record() qui fait la même chose mais qui en retourne qu'un seul.

// tableau associatif
$list = dns_get_record('gmail.com', DNS_MX);
print_r($list);
Faites gaffe au moment de l'utiliser, la première fois que je l'ai essayé, je n'avais pas remarqué qu'il fonctionnait à l'aide de constantes. En effet, le deuxième argument est bel et bien une constante et non une chaîne de caractères (DNS_SOA et non 'DNS_SOA'). Ça facilitera nettement les choses si vous utiliser un IDE qui possède une fonction d'auto-complétion : entrez "DNS_" et vous verrez apparaître les valeurs possibles dont DNS_SOA, DNS_MX, DNS_A, etc (une douzaine de possibilités).

Une petite recommandation : si vous souhaitez seulement vérifier l'existence d'un record, vous pourrez vous contenter des fonctions "check" comme checkdnsrr() ou son alias checkdnsrr().

Lorsqu'un utilisateur entrera un courriel dans son profil, vous pourrez vous assurer que le domaine existe (sans toutefois savoir si le compte, la partie avant le @, est réel) puisque la fonction retourne un booléen pour indiquer vrai ou faux.
$result = checkdnsrr('gmail.com');
Pour finir, une dernière remarque : si vous comptez l'utiliser sur un environnement Windows, sachez que les fonctions réseau de PHP ne sont disponible qu'à partir de la version 5.3.


Tags: Coffre à outils, Linux, PHP

lundi 20 juillet 2009

Parkinson en milieu de travail

Publié par Infinite Loop, à 20 h 23 2 commentaires

Le titre est intriguant, n'est-ce pas ? Je ne voulais pas parler de la maladie dont le nom a été donné en raison du physicien James Parkinson (1755–1824) qui l'a décrite. Non, je faisais référence à l'autre Parkinson, Cyril Northcote Parkinson (1909–1993), celui qui a énoncé la loi éponyme!

Comme mon patron, lorsque je lui en ai parlé pour la première fois, vous pouvez vous moquer de moi. Après tout, je n'y peux rien si elle existe. Quand on la connaît, elle fait bien du sens et explique beaucoup de choses.

La loi stipule que :

Le travail s’étale de façon à occuper le temps disponible pour son achèvement.

Qu'est-ce que ça veut dire ? Que dans tout environnement où se trouve le facteur H (humain), un gestionnaire assigne une tâche à un employé avec un délai prescrit pour la compléter. Si l'expérience du travailleur fait en sorte qu'il pourrait réussir à l'achever en moins de temps que ce qui lui a été assigné, une bouffée de paresse atteint la dite personne qui s'efforcera d'étirer et d'utiliser la totalité de la période pour en venir à bout.

C'est un comportement très répandu en Amérique du Nord et c'est certainement contradictoire avec la mentalité Kaizen. Après, on se demande pourquoi les asiatiques produisent une meilleure qualité de produits que nous (NDLR: on a qu'à penser aux voitures).

Maintenant, si je l'adapte à mon milieu de travail (la programmation), lorsqu'il y a des évaluations de temps réalisées pour la planification d'un projet, si le temps est dépassé par l'équipe de production, les développeurs accuseront l'analyste a mal fait son travail (en sous-estimant la charge à produire). En revanche, si le programmeur est plus rapide, il est sera un héros aux yeux de ses supérieurs.

Qu'en est-il lorsque c'est le programmeur qui réalise l'estimation ? Deux possibilités. Soit qu'il y va en toute honnêteté et qu'il mettra tout en oeuvre pour terminer le travail dans les délais annoncés pour ne pas perdre la face et devoir avouer son erreur, soit il aura tendance à sur-estimer volontairement le temps que ça lui prendra et il appliquera la loi de Parkinson. Normalement, il s'arrangera pour livrer la marchandise dans les délais prévus, autrement ça lui laisse quelques temps libres pour aller prendre des toasts et un café...

Et vous, vous avez des bonnes histoires à ce sujet ?


Tags: Lois et principes

dimanche 19 juillet 2009

Performance JavaScript

Publié par Infinite Loop, à 11 h 12 0 commentaire

Ce matin, comme j'avais installé les plus récentes versions de Firefox 3.5.1, Internet Explorer 8 et Chrome 2, j'ai décidé de livrer leurs engins JavaScript respectifs au petit test de benchmark SunSpider.

Les fureteurs testés utilisent les engins suivants :

Internet Explorer 8 : JScript
Firefox 3.5 : SpiderMonkey avec les ajouts de TraceMonkey
Chrome 2 : V8

Résultats pour SunSpider JavaScript Benchmark :

Internet Explorer 8 : 7950.0 ms
Firefox 3.5 : 1955.4 ms
Chrome 2 : 918.4 ms

Selon ce test de performance, le JavaScript roule 8.6x plus vite sous Chrome que IE! Ceci est dû à l'engin JavaScript open-source V8 ultra-performant que Google a développé spécifiquement pour son fureteur.

Un autre test de performance qu'on peut prendre comme référence est le V8 Benchmark Suite (version 5). Ici, le score n'est pas calculé en temps mais en points, donc plus il est élevé, meilleure est la performance.

Résultats pour V8 Benchmark Suite :

Internet Explorer 8 : 51 pts
Firefox 3.5 : 218 pts
Chrome 2 : 1917 pts

Sans surprise, Chrome arrive au premier rang avec une vitesse 8 fois plus rapide que son plus proche rival, ce qui lui fait une belle publicité pour son produit maison (mais n'a-t-il pas été réglé pour faire bien paraître son engin V8 ? Ça reste à voir...). De son côté, Firefox 3.5 ne paraît pas trop mal, surtout qu'il est 2x plus rapide que la version précédente. Enfin, même si IE 8 n'est plus dans la course, il se mérite quand même un prix de présence. Comme dirait le vieil adage, l'important n'est pas de gagner, mais de participer. Hum... pas tout le temps!


Tags: JavaScript

Citation no. 39 sur l'imbécilité

Publié par Infinite Loop, à 09 h 56 0 commentaire



I pity the fool !

- Mr T.


Tags: Citations

samedi 18 juillet 2009

Créer un singleton en JavaScript

Publié par Infinite Loop, à 11 h 20 3 commentaires

En programmation, on connait bien le pattern Singleton où une restriction autorise l'utilisation d'une seule instance de la classe. Mais comment l'implémenter en JavaScript ?

L'objectif d'un singleton, c'est de ne pas pouvoir instancier la classe, ce qui nous permettrait d'avoir différentes copies. C'est pourquoi on demandera à l'objet de nous retourner l'instance unique à utiliser, et ce, sans utiliser la notation "new". L'utilisation de ce pattern est justifié par le fait que deux objets du même type ne devraient pas coexister dans l'application. Un autre exemple se trouve dans un système d'exploitation, où plusieurs logiciels roulent comme des singletons : on s'assure que le processus est lancé une seule fois.

Ici, je ferai en sorte d'obtenir un objet de configuration unique pour mon application web. Ainsi, on veut restreindre le programmeur à faire ceci :

// erreur!
var obj = new AppConfiguration();
Voici un gabarit de base en JavaScript pour implémenter un singleton.
function AppConfiguration() {

// quelques propriétés
this.language = 'fr';
this.currency = 'CAD';
this.currencySymbol = '$';
this.dateFormat = 'yyyy-mm-dd';

if ( AppConfiguration.caller != AppConfiguration.getInstance ) {
throw new Error("This object cannot be instanciated");
}
}

// propriété statique qui contient l'instance unique
AppConfiguration.instance = null;

AppConfiguration.getInstance = function() {
if (this.instance == null) {
this.instance = new AppConfiguration();
}

return this.instance;
}
Dans le constructeur, c'est là que la magie s'opère. On vérifie la propriété caller qui retourne une référence à la fonction qui a appelé la fonction courante. Autrement dit, on retourne un objet seulement et seulement si ça a été demandé par la méthode getInstance.

Bien sûr, on peut appeler plusieurs fois getInstance() mais les propriétés de l'objet seront les mêmes pour les deux "objets" puisqu'en réalité, il s'agit du même comme le démontre le test ci-dessous :
var obj1 = AppConfiguration.getInstance();

// valeur par défaut: fr
console.log(obj1.language);

// changer la langue pour anglais
obj1.language = 'en';

// récupérer l'instance dans une autre variable
var obj2 = AppConfiguration.getInstance();

// la propriété language de obj2 vaut "en"!
console.log(obj2.language);

// changer la langue du 2ème objet
obj2.language = 'klingon';

// klingon
console.log(obj1.language);

// klingon
console.log(obj2.language);
Au final, même si l'objet est référencé par deux variables, elles pointent vers la même instance. Changer la propriété à une ou l'autre des variables se répercutera à l'objet unique.


Tags: JavaScript

vendredi 17 juillet 2009

Compiler un programme en C++

Publié par Infinite Loop, à 15 h 19 1 commentaire

Après des mois d'hésitation et un regain de curiosité, j'ai décidé de me replonger doucement dans le monde du C/C++. La dernière fois que j'en ai codé remonte à mes cours au Cegep où on utilisait des IDE comme Turbo C et Visual C++.

Même si ce n'est pas quelque chose que j'utilise normalement dans ma vie professionnelle, c'est toujours un must de savoir se débrouiller avec ce langage. Je n'ai pas la prétention d'être un guru dans ce domaine mais je tenais au moins à présenter une petite introduction à la compiulation d'un programme en C++.

D'abord, il faut savoir qu'il exite plusieurs compilateurs sur le marché, mais j'ai choisi d'y aller avec GCC (GNU Compiler Collection, originalement GNU C Compiler) car il est gratuit, disponible autant pour Linux que Windows et parce que ça ne sert pas juste à compiler du C/C++, d'où le nom "Collection").

Premièrement, nous avons besoin d'un échantillon de code source fonctionnel. Celui-ci fera l'affaire pour la démonstration.

#include <iostream>

using namespace std;

int main ()
{
int i;

for(i=1 ; i<=10; i++){
cout << i;
cout << '\n';
}

return 0;
}
Nommons ce fichier "test.cpp".

Ensuite, dans la collection de GCC, il se trouve un front-end pour C++ nommé "g++". C'est celui-ci que nous utiliserons car il est construit spécifiquement pour compiler des programmes écrits en C++.

À partir du code source, nous pourrons le transformer en code machine avec la commande suivante (à supposer que vous êtes dans le répertoire où se trouve le code source) :

g++ test.cpp

Si tout s'est bien passé, le résultat sera un fichier d'output exécutable nommé "a.out" (nom par défaut si aucun autre nom spécifié). Nous préférerons généralement lui donner un nom plus approprié en utilisant le flag -o suivi du nom :

g++ test.cpp -o test

Sur Linux, on exécutera le programme comme ceci : ./test

On peut aussi utiliser en partie le compilateur gcc pour compiler du C++ (plutôt que g++). Pour y arriver, il faut spécifier le flag "-x c++" pour indiquer le langage à utiliser.

gcc -c -x c++ test.cpp

Ceci créera un fichier test.o, c'est-à-dire un objet binaire compilé sans que le linker (liaison/édition de liens) ait passé dedans. Les fichiers .o représentent différents objets qui peuvent être assemblés ensemble pour créer un exécutable unique. C'est pourquoi on doit passer par le linker et cette étape ne peut être réalisée que par g++. C'est lui qui sera en mesure de faire le travail pour inclure les librairies C++ nécessaires au bon fonctionnement du programme.

g++ test.o -o test

Généralement, on préférera utiliser g++ d'un bout à l'autre de l'opération.

Pour Windows, c'est essentiellement la même chose. On pourra se procurer la suite GCC à plusieurs endroits, on un est fournit avec le bundle de l'éditeur gratuit Bloodshed Dev-C++.

Si vous désirez compiler à partir de l'invite de commandes, vous devrez soit :
  • naviguer dans le répertoire où se trouve le compilateur
  • inclure le chemin des exécutables dans Environment Variables de Windows
Compiler sous Windows :
g++ c:\path\vers\source.cpp -o c:\path\vers\resultat.exe

Exécuter : resultat.exe

Voilà, vous devriez voir apparaître 10 lignes numérotées de 1 à 10 générées par la boucle for. Un dernier conseil : évitez de faire une boucle infinie...

for ( ; ; );

Bon weekend à tous!


Tags: Linux, Programmation

jeudi 16 juillet 2009

Virus Newton

Publié par Infinite Loop, à 19 h 28 0 commentaire

Sur un PC avec Windows, les risques que votre ordinateur attrape un virus sont généralement élevés puisque le populaire OS est constamment la cible des gens mal intentionnés. Sur Linux ou Mac OS X, c'est plus rare.

Pourtant, plusieurs amateurs de Mac sont prêts à payer pour obtenir un virus : le Newton.



Ce "virus" qui n'en est pas un prend avantage du capteur installé sur les MacBooks pour simuler l'effet de la gravité sur les éléments du bureau. Lorsqu'il est physiquement manipulé, les objets se mettent à bouger, glisser et tomber.



Disponible à partir de OS 10.4 Tiger, ce petit gadget saura vous amuser et faire sourire votre entourage que vous prendrez plaisir à infecter. À se procurer pour moins de 10$ sur le site de Troika.uk.com.


Tags: Curiosités

mercredi 15 juillet 2009

Installer browscap.ini pour PHP

Publié par Infinite Loop, à 20 h 44 0 commentaire

Dans un contexte d'application ou de site web où la compatibilité du fureteur doit être vérifiée, on sait qu'il se présente au serveur en envoyant une chaîne de caractère qu'on appelle "User Agent" et qu'on peut la récupérer en PHP par $_SERVER['HTTP_USER_AGENT'].

Par exemple, celui du fureteur que j'utilise actuellement est :

Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.4) Gecko/2008111217 Fedora/3.0.4-1.fc10 Firefox/3.0.4

Vous pouvez connaître facilement votre user agent ici.

Si on veut extraire les différentes parties, ça peut être un peu compliqué. On pourrait utiliser une classe PHP comme Browser Detect, ou encore configurer PHP avec browscap.ini pour utiliser la fonction native get_browser(). C'est ce que nous allons faire.

Pour l'installer :

  • rendez-vous à la page de téléchargement
  • téléchargez le fichier php_browscap.ini (assurez-vous de prendre celui pour PHP)
  • vous devez le déposer sur votre serveur:
    • Linux : n'importe où, par exemple, dans le répertoire "extra" (voir plus bas)
    • Windows : selon ce que j'ai testé, il semble y avoir une limitation et on doit placer ce fichier dans C:\WINDOWS\system32\inetsrv\
  • ouvrez votre fichier php.ini
  • repérez la ligne de configuration [browscap]
  • entrez le chemin absolu qui pointe vers le fichier .ini. Par exemple :

    [browscap]
    browscap = C:\WINDOWS\system32\inetsrv\php_browscap.ini

    ou

    [browscap]
    browscap = extra/browscap.ini

  • Redémarrez Apache
Une fois ces opérations complétées, vous devriez voir le chemin du fichier dans la section PHP Core de phpinfo(). Par contre, vous ne savez pas si le chemin est exact et si ça fonctionne.

Il faut vérifier si PHP en tient compte. Mais attention, la ligne suivante vous indiquera si la configuration est trouvée, mais pas si elle est fonctionnelle (ça indiquera "Configuré" si un chemin a été inscrit).
echo get_cfg_var('browscap') ? 'Configuré' : 'Pas configuré';
Appelez maintenant la fonction native get_browser(). Le premier paramètre est le user agent à évaluer. Si null est passé, celui par défaut sera utilisé (la variable serveur HTTP_USER_AGENT). Le deuxième permet d'indiquer comment les parties extraites sont retournées. True retourne un tableau au lieu d'un objet stdClass (notation flèche).
$info = get_browser(null, true);

# voir toutes les valeurs du tableau
print_r($info);

# une valeur précise
echo $info['browser'];
echo $info['version'];
Finalement, vous devrez prévoir une maintenance périodique sur ce fichier pour le mettre à jour avec les plus récentes versions de fureteurs connus, obscurs et ceux à venir.


Tags: PHP

mardi 14 juillet 2009

Qui se souvient du VRML ?

Publié par Infinite Loop, à 22 h 34 4 commentaires

N'essayez pas de comprendre comment j'en suis venu à parler du VRML (Virtual Reality Modeling Language). En fait, si vous me le demandez, ce n'est pas par nostalgie mais bien parce que je suis tombé par hasard sur un livre qui trainait dans ma bibliothèque et qui accumulait la poussière. Vous savez, le genre de bouquin sorti trop vite suite à un buzz inexpliqué et dont l'engouement pouvait laisser croire que l'avenir du web s'y trouvait ? La preuve que c'était un gage de qualité, il était assorti d'un CD-ROM qui comprenait une centaine de démos et de programmes gratuits et commerciaux (avouez, vous êtes jaloux!). Le titre : 3D Graphics and VRML 2 par Laura Lemay. Sans farce, je suis un peu gêné de le posséder, surtout que si je me fie au prix à l'endos, j'aurais payé 56,95$ canadiens pour ça...

J'ai dû me le procurer aux alentours de 1996 ou 1997 et en feuilletant les pages une douzaine d'années plus tard, je suis vraiment rassuré de constater que ça n'a pas connu la popularité espérée. Internet est devenu un lieu beaucoup plus respectable qu'un environnement en 3 dimensions comme le laissaient sous-entendre certains films de science fiction. Au mieux, n'y avait-il pas eu des chambres de clavargage 3D pour concurrencer mIRC ?

Pour vous donner une idée de ce qu'avait l'air le code VRML, voici un court extrait qui génère un objet 3D représentant un tank et le rendu graphique :

#VRML V1.0 ascii

Separator {
ShapeHints {
vertexOrdering COUNTERCLOCKWISE
faceType CONVEX
creaseAngle 0.5
}
Transform {
rotation 0.577317 0.577317 0.577417 4.18889
center -0.00745004 -1.0287 -0.1012
}
Separator {
Coordinate3 {
point [ 0.46228 1.3716 0.00039983,
0.46228 1.4275 -0.0029025,
1.0033 1.3716 0.00039983,
0.90678 1.6446 -0.015857,

Source : ocnus.com

Une fois le plugin installé, on pouvait visionner les fichiers .wrl, manipuler les objets en 3D avec la rotation, se promener dans les environnements, etc. Même aujourd'hui, alors que je voulais constater ce qu'était devenu cette technologie, j'ai installé Cotrona 3D Viewer et j'ai quand même trouvé la navigation difficile.

Aussi, quand je pense à la "réalité virtuelle", je n'ai pas d'autre choix que de me rappeler l'échec du jeu vidéo Virtual Boy de Nintendo.

Comme dirait l'équipe de C'est juste de la TV, c'est ce que j'envoie au réparateur cette semaine. Quelqu'un est intéressé ou j'en fais cadeau au recyclage ?


Tags: Livres

lundi 13 juillet 2009

Star Wars et Telnet

Publié par Infinite Loop, à 19 h 57 0 commentaire

Un vieux trésor que j'ai retrouvé dans un fond de tiroir... Vous aurez compris que c'était pour cette raison que je testais Telnet hier matin!

Contrairement à la croyance populaire, ce n'est pas un "easter egg" car ça ne fait pas parti d'une zone cachée d'un système d'exploitation ou d'un logiciel, mais c'est quand même digne de mention pour ceux qui ne l'avaient jamais vu.

Avec un command prompt ou un terminal, entrez ceci :

telnet towel.blinkenlights.nl

Vous verrez un bel exemple de ce qu'est du "asciimation".



Profitez du film, vous avez accès à la version complète de Star Wars: Episode IV - A New Hope :-)



Dans la même lignée, connectez-vous sur le port 666 du même serveur pour bénéficier d'un service gratuit d'excuses aléatoires, gracieuseté de BOFH : Bastard Operator From Hell.

telnet://towel.blinkenlights.nl:666

Une version web de BOFH et de Star Wars sont aussi disponibles pour ceux qui craignent Telnet.


Tags: Curiosités

dimanche 12 juillet 2009

Installer Telnet pour Windows 7 et Vista

Publié par Infinite Loop, à 08 h 59 1 commentaire

En prévision d'un sujet que je voulais aborder dans les jours à venir, j'ai frappé un mur en voulant tester Telnet sur Windows 7. Contrairement à Windows XP, il ne s'y trouve plus par défaut depuis Vista.

Selon l'équipe de Microsoft, Telnet a été retiré pour deux raisons :

  • c'est un programme de moins en moins utilisé par les utilisateurs
  • ça permet de réduire les possibilités d'attaques contre son système d'exploitation
Heureusement, on peut ajouter le client Telnet assez facilement :
  • Assurez-vous d'avoir les droits d'administrateurs sur votre système
  • Ouvrez un invite de commande (Start / Exécuter cmd)
  • Entrez la ligne suivante : pkgmgr /iu:TelnetClient
  • Exécutez la en appuyant sur la touche "Enter"
Enfin, pour ajouter la version Serveur : pkgmgr /iu:TelnetServer


Tags: Coffre à outils

Citation no. 38 sur la perfection

Publié par Infinite Loop, à 08 h 30 0 commentaire

La perfection est atteinte, non pas lorsqu'il n'y a plus rien à ajouter, mais lorsqu'il n'y a plus rien à retirer.

- Antoine de Saint-Exupéry


Tags: Citations

samedi 11 juillet 2009

Internet Explorer et les messages simplifiés

Publié par Infinite Loop, à 09 h 54 0 commentaire

Pour un développeur web, il n'y a rien de plus frustrant (jusqu'à preuve du contraire) que de développer avec le fureteur Internet Explorer. Suite à la lamentable version 6, on a dû attendre 5 ans pour apercevoir IE7 (simultanément avec la sortie de Windows Vista) et la dernière mouture d'IE 8 commence à être "programmer friendly" en répiquant les meilleures idées de Firefox et autres browsers concurrents.

Certes, la stratégie de Microsoft est de viser le grand public, monsieur et madame tout-le-monde, ceux qui se soucient bien peu de la mécanique interne d'un site web. Nous, en tant que professionnels du métier, nous devons inmanquablement tester avec cette famille de fureteur utilisée par 66% de la population Internet (mai 2009).

Quand on teste un projet web avec IE, contrairement à la majorité, nous ne souhaitons pas voir les messages d'erreurs amicaux qui s'adressent à la masse comme le montrent les imprimés d'écrans ci-dessous. Nous ce qu'on veut, ce sont les vraies erreurs provenant des réponses HTTP (en particulier les erreurs 500 qui se produisent côté serveur).

Internet Explorer 6


Internet Explorer 8


Alors comment désactiver les messages simplifiés pour mieux comprendre les erreurs pendant le développement ?

On doit faire un passage obligé par la configuration :

  • Menu Tools
  • Internet Options
  • Onglet Advanced
  • Trouvez l'option qui se nomme "Show friendly http error messages" ou "Afficher des messages d'erreurs simplifiés"
  • Décochez la case
  • Cliquez OK
Pourtant, je trouve curieux que cette option se retrouve dans la configuration avancée alors que Developers Tools (F12) est accessible facilement par tous, particulièrement ceux qui n'en ont pas besoin. Ça pourrait être bien que l'option s'y retrouve ou encore, dès que l'outil est ouvert, le fureteur pourrait basculer en mode "développeurs" et ajuster ses paramètres pour nous faciliter la tâche.


Tags: Programmation

vendredi 10 juillet 2009

Désactiver un trigger sous SQL Server

Publié par Infinite Loop, à 15 h 31 0 commentaire

J'ai récemment vécu la situation suivante : dans une base de données SQL Server, une table possédait un trigger qui était déclenché lorsque des données étaient manipulées. Entre autre (pour garder l'exemple simple), la date de dernière modification était automatiquement mise à jour lors des énoncés UPDATE.

Lors d'une maintenance, comme j'avais une série de manipulations à faire dont l'ajout et l'initialisation d'un nouveau champ selon des données compilées du système, le trigger se serait déclenché automatiquement pour chaque enregistrement, ce qui aurait écrasé inutilement les dates de dernières mises à jour ainsi que de provoquer une augmentation considérable dans le temps d'exécution (1 fois pour chaque rangée de la table).

Pour contourner le problème et minimiser le down time, j'ai tout simplement placé le système en mode maintenance et désactivé temporairement les triggers, le temps d'effectuer ma série de commandes. Une fois complétée, je les ai réactivés. L'avantage de cette technique est que les triggers existent toujours dans le système mais que ses règles ne sont pas appliquées. Ça nous évite surtout de devoir les supprimer pour ensuite les créer à nouveau.

Avec SQL Server, on peut désactiver un trigger en spécifiant le nom de la table et le nom du trigger, ou en utilisant le mot clé "ALL" pour désactiver tous ceux associés à la table.

-- Activation
ALTER TABLE tablename DISABLE TRIGGER triggername;
ALTER TABLE tablename DISABLE TRIGGER ALL;

-- Réactivation
ALTER TABLE tablename ENABLE TRIGGER triggername;
ALTER TABLE tablename ENABLE TRIGGER ALL;
Depuis SQL Server 2005, on peut aussi utiliser la syntaxe suivante :
DISABLE TRIGGER triggername ON tablename;
DISABLE TRIGGER ALL ON tablename;

-- et inversement

ENABLE TRIGGER triggername ON tablename;
ENABLE TRIGGER ALL ON tablename;
En quelques secondes, la maintenance était terminée. Ma suggestion : mémorisez la premiere syntaxe puisqu'elle est plus répandue dans les différents types de RDBMS (Relational database management system) alors que DISABLE TRIGGER est une approche non standard de Microsoft.


Tags: SQL Server

jeudi 9 juillet 2009

Impression avec saut de page en CSS

Publié par Infinite Loop, à 19 h 07 0 commentaire

C'est une chose de faire de la mise en page pour le web, c'en est une autre de pouvoir l'imprimer correctement. En fait, ce n'est pas tout à fait évident, surtout quand on veut faire imprimer une liste de type "publipostage", où on doit faire un saut de page pour créer des lettres distrinctes. Lorsqu'on détecte un nouvel enregistrement, on veut passer à la page suivante pour le prochain envoi plutôt que de poursuivre l'impression sur la même page.

Le truc que j'ai trouvé pour palier à ce problème est d'utiliser une propriété CSS : page-break-after. À partir de ce snippet de code HTML, on peut appliquer le CSS comme suit :

<h3>Page 1</h3>
<p>Lorem ipsum dolor sit amet...</p>
<br style="page-break-after:always;" />

<h3>Page 2</h3>
<p>Lorem ipsum dolor sit amet...</p>
<br style="page-break-after:always;" />

<h3>Page 3</h3>
<p>Lorem ipsum dolor sit amet...</p>
Faites un aperçu avant impression (print preview) et vous verrez que chaque entête se retrouve sur une page différente. Évitez aussi d'en placer un après le dernier bloc si vous ne voulez pas imprimer une page blanche.

Dire qu'on disait qu'avec l'arrivée de l'informatique, on imprimerait moins de papier. Visitez le site w3schools.com pour en apprendre plus sur les styles CSS pour l'impression et devenez maître dans l'art de faire gaspiller des feuilles blanches à vos clients!


Tags: CSS

mercredi 8 juillet 2009

Trucs pour inverser la valeur d'un booléen

Publié par Infinite Loop, à 20 h 11 0 commentaire

Ah la puissance de la négation !

À main levée, combien d'entre vous programmez des conditions if/else pour inverser la valeur d'un champ booléen ? Réfléchissez à la dernière fois où vous avez codé un tableau HTML dynamique en alternant la couleur des lignes (sauf si bien sûr vous utilisez le truc du modulo...).

Maintenant, vous rappelez-vous des cours élémentaires d'algèbre : ¬p (non p) ? En programmation, on a intérêt à en profiter. Voici quelques exemples dans différents contextes.

PHP
On le retrouve habituellement sous deux formes :

# 1. if/else
$var = true;

if($var == true){
$var = false;
}
else {
$var = true;
}

var_dump($var); // false

# 2. opérateur ternaire
$var = $var ? false : true;
var_dump($var); // true
Alors qu'une seule négation aurait suffit :
$var = true;
$var = !$var;

var_dump($var); // false
PostgreSQL
Ici, on accède à la négation par le mot clé NOT :
UPDATE table
SET boolean_value = NOT boolean_value
WHERE id = 1;
SQL Server
Le type boolean n'existe pas sous SQL Server. Son équivalent est le BIT et on peut utiliser l'opérateur bitwise (~) pour créer une négation:
UPDATE table
SET bit_value = ~bit_value
WHERE id = 1;
JavaScript
On n'y pense peut-être pas toujours mais les objets en HTML possèdent aussi des propriétés booléennes qu'on peut inverser à l'aide de JavaScript. Ainsi, une case à cocher possède l'attribut "checked" qui est un booléen.

Un exemple avec Prototype :

HTML
<a href="javascript:;" id="aReverse">Inverser</a>
<input type="checkbox" id="chk1" value="1" />
JavaScript
Event.observe('aReverse', 'click', reverse );

// façon masochiste
function reverse(){
if( $('chk1').checked ){
$('chk1').checked = false;
}
else {
$('chk1').checked = true;
}
}

// pour le programmeur paresseux
function reverse(){
$('chk1').checked = ! $('chk1').checked;
}
P.s. ne levez pas la main pour vrai! ;-)


Tags: Programmation

mardi 7 juillet 2009

Principe : Fake It

Publié par Infinite Loop, à 21 h 16 0 commentaire

Peu importe le langage de programmation, il existe une méthodologie de travail que vous utilisez peut-être durant le développement, probablement sans même vous en rendre compte : Fake It ('Til You Make It).

Cette approche, décrite par Kent Beck dans son livre Test-Driven Development by Example (TDD), suggère que lorsqu'on écrit les tests avant de se lancer dans l'implémentation du code, l'objectif premier étant de faire passer la suite de tests avec succès (et surtout d'avoir des tests!). Apercevoir la barre verte qui indique que tout fonctionne bien peut être bénéfique pour le moral, même si on implémente le tout avec des classes et des fonctions bidons. Au moins la structure et la logique tiennent la route. Et lorsque vient le temps de faire des changements ou du refactoring, il suffit d'exécuter à nouveau la série de tests pour s'assurer que tout est conforme.

L'autre avantage est d'avoir un meilleur contrôle sur chaque composant du code, et ce même si on ne respecte pas l'approche TDD. Par exemple, si on sait que notre projet sera constitué d'un mécanisme de login ou encore d'un service web qui retourne un taux de change, on peut créer le squelette des classes et le prototype des fonctions qui retourneront des valeurs "hard-codées" en attendant la création du code final. Ensuite, il restera à déléguer l'implémentation à d'autres membres de l'équipe le temps venu.

C'est pourquoi on dit "feint le ou imite le en attendant de le compléter".

Quelques exemples de patterns Fake It :

# exemple 1
function hasAccess($level, $resource){
// hard-coded return value
return true;
}

if( hasAccess('pickpocket', 'wallet') ){
// do something
}

# exemple 2
function getCurrentCurrencyExchangeRate($from, $to){
// @todo: connect to live service
return 1.16452;
}

echo getCurrentCurrencyExchangeRate('USD', 'CAD');


Tags: Lois et principes

lundi 6 juillet 2009

Exécution avec des backticks en PHP

Publié par Infinite Loop, à 16 h 44 0 commentaire

En lisant un exemple de code source PHP qui démontrait comment récupérer le process id (pid) d'un processus roulant sur un serveur Linux, j'ai découvert une notation que je ne soupçonnais pas. En me référant à la documentation PHP, j'ai vu qu'on pouvait substituer l'appel à la fonction shell_exec() par l'opérateur backtick (``). Attention, ce n'est pas une erreur de typo, c'est bel et bien le caractère pour les accents graves (ALT+96 sur le clavier numérique) et non des guillemets simples.

Les deux instructions suivantes sont équivalentes :

$pid = `pidof firefox`;

$pid = shell_exec('pidof firefox');

echo $pid; // 3216

# voir ps -A pour obtenir la liste de tous les processus
Même si je connais maintenant cette alternative, je crois que je vais quand même préférer utiliser la notation qui facilitera le plus la compréhension au moment de relire le code dans un futur plus ou moins rapproché (à moins bien sûr de laisser un commentaire concernant le backtick pour éclairer le prochain programmeur qui y mettera son nez).


Tags: Linux, PHP

dimanche 5 juillet 2009

Ne volez pas cette regex de courriel !

Publié par Infinite Loop, à 10 h 56 2 commentaires

Pour valider une adresse électronique avec une expression régulière compatible Perl (PCRE), on pourrait supposer qu'une regex comme celle-ci suffirait :

[\w-]+@([\w-]+\.)+[\w-]+

Cependant, ça pourrait être beaucoup plus complexe ! En effet, si on veut respecter le standard RFC822, on devrait valider beaucoup plus d'éléments et ses restrictions :

(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:
\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(
?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[
\t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\0
31]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\
](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+
(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:
(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)
?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\
r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[
\t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)
?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t]
)*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[
\t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*
)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)
*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+
|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r
\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t
]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031
]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](
?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?
:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?
:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?
:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?
[ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\]
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|
\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>
@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"
(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?
:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[
\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-
\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(
?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;
:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([
^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\"
.\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\
]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\
[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\
r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\]
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]
|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \0
00-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\
.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,
;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?
:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[
^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]
]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*(
?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(
?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[
\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t
])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t
])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?
:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|
\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:
[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\
]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)
?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["
()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)
?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>
@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[
\t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,
;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:
\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[
"()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])
*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])
+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\
.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(
?:\r\n)?[ \t])*))*)?;\s*)

Comme disait Jeffrey Friedl, la taille de la regex n'a rien à voir avec son efficacité. Elle permet simplement de déterminer plus rapidement si le match est un succès ou un échec.

Malheureusement, on ne peut pas se fier à cette longue expression pour valider les courriels. Elle respecte la définition officielle de la syntaxe d'une adresse électronique définie en 1982 donc avant même l'apparition d'Internet tel qu'on le connaît aujourd'hui. Elle a depuis été remplacée par le RFC5322.

La regex suivante pourrait être plus appropriée pour valider un courriel :

^[^0-9][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*[@][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*[.][a-zA-Z]{2,4}$

Rappelez-vous que même en composant l'expression la plus précise, cela ne vous garantira pas que l'adresse existe.


Tags: Perl, PHP, Programmation

Citation no. 37 sur le doute

Publié par Infinite Loop, à 08 h 41 0 commentaire

When in doubt, use brute force

- Ken Thompson


Tags: Citations

samedi 4 juillet 2009

Instruction GOTO de PHP 5.3

Publié par Infinite Loop, à 19 h 32 0 commentaire

L'arrivée officielle de PHP 5.3 annonce aussi l'apparition de l'instruction controversée "goto". Certains l'apprécient, d'autres la détestent, mais une chose est sûre, c'est qu'on devra traiter avec elle à l'avenir.

Présent dans plusieurs autres langages, le programmeur qui voudra utiliser GOTO pourra le faire en indiquant une étiquette (label) où le script fera le saut à l'endroit spécifié dans le code pour poursuivre l'exécution. Heureusement, le goto de PHP est restrictif : le saut et le label d'arrivée doivent se trouver dans le même fichier et le même contexte pour que ça fonctionne. L'utilisation suggérée est de faire un bris (break) à l'intérieur de boucles imbriquées:

for($i=0,$j=50; $i<100; $i++) {
while($j--) {
if($j==17) goto end;
}
}
echo "i = $i";
end:
echo 'j hit 17';
Toutefois, bien que ça puisse rendre service dans certaines circonstances, l'apparition de cette commande présente aussi un côté négatif : certains développeurs risquent d'en abuser. Non seulement le résultat devient du code spaghetti, il ne sera pas compatible avec les plus vieilles versions de PHP et sera plus difficile à suivre. D'ailleurs, il y a un excellent comic à lire à ce sujet sur xkcd.

Comme le mentionnait Johannes Schlüter (release manager pour la version PHP 5.3), il existe au moins deux cas où ça peut être pratique:
  • dans un générateur de code
  • pour annuler l'exécution d'une portion de code tout en s'assurant d'effectuer le nettoyage à la fin
function process_file($filename) {
$fp = fopen($filename, "r");
if (!$fp) {
goto cleanup;
}

$row = fread($fp, 1024);
// do something with the row
if ($error_while_processing) {
goto cleanup;
}

$a_few_bytes = fread($fp, 4);
// do something again ...
if ($error_while_processing) {
goto cleanup;
}

/* ... */cleanup:
fclose($fp);
}
Gardez en tête que c'est présent mais surtout, évitez de l'utiliser le plus possible, sauf en cas d'extrême nécessité. Il y a toujours une autre approche possible (il suggère un break ou un try/catch).


Tags: PHP

vendredi 3 juillet 2009

Cacher un fichier dans une image

Publié par Infinite Loop, à 20 h 21 0 commentaire

Voici un truc simple pour cacher un fichier à l'intérieur d'une image. Le fichier sera incorporé au coeur du code binaire de l'image ce qui aura pour effet qu'elle pourra être vue normalement suite à la fusion, sans se douter qu'elle contient un fichier!

  1. D'abord, choisissez une image (j'ai essayé avec succès un JPG et un PNG)
  2. Identifiez un fichier à cacher (j'ai essayé avec un PDF)
  3. Pour simplifier l'opération, regroupez vos fichiers dans le même répertoire
  4. Ouvrez un invite de commande (Start / Run / cmd)
  5. Rendez-vous au dossier où vous avez placé les fichiers
  6. Lancez la copie en mode binaire (/b) :

    copy /b image-originale.jpg + document.pdf image-injectee.jpg

    où on additionne les fichiers avec l'opérateur + pour créer en sortie le fichier image-injectee.jpg
  7. Vous pouvez ouvrir la nouvelle image normalement. Vous remarquerez que sa taille est plus élevée en raison du fichier dissimulé
Pour récupérer le fichier, il suffit de renommer l'extension .jpg par .rar et d'ouvrir l'archive avec WinRar pour l'extraire.

Après l'injection, j'ai réussi à convertir le format de l'image trafiquée avec ImageMagick mais la récupération du fichier caché fût impossible par la suite (évidemment). J'aurais aimé vous fournir le résultat ici pour que vous puissez le constater mais comme Blogger redimentionne les images automatiquement au moment du transfert, vous n'aurez pas le choix de le tester par vous-même.


Tags: Sécurité

jeudi 2 juillet 2009

Obtenir le statut d'exécution d'une requête PostgreSQL

Publié par Infinite Loop, à 19 h 31 0 commentaire

Vous savez que lorsqu'on exécute un énoncé SQL, le serveur répond habituellement avec un message indiquant le nombre d'enregistrements qui ont été affectés par la requête.

Sur PostgreSQL, si on utilise un éditeur comme pgAdmin III, on peut voir le statut dans l'onglet Message de l'Output Pane.

Avec une table comme celle-ci (excusez mon exemple simpliste) :

CREATE TABLE tbl
(
id serial NOT NULL,
title character varying(255)
)
Si on effectue une mise à jour en lot (mieux connu sous le nom de "batch update") ou une insertion de plusieurs enregistrements à partir du même énoncé :
INSERT INTO tbl(title)
VALUES ('ABC'), ('DEF'), ('XYZ');

-- OU

UPDATE tbl
SET title = lower(title);
On verra apparaître un statut semblable au suivant :

Query returned successfully: 3 rows affected, 31 ms execution time.

Qu'est-ce qu'on peut faire si on veut récupérer le nombre d'enregistrements affectés par la commande (comme ce fût le cas pour moi aujourd'hui) ?

Il suffit de faire exécuter la requête SQL à l'intérieur d'une fonction PostgreSQL et d'utiliser immédiatement après une instruction du langage PL/pgSQL qu'on attribue à une variable.
CREATE OR REPLACE FUNCTION insert_some_rows() RETURNS integer AS
$BODY$
DECLARE
cnt integer;
BEGIN
UPDATE tbl
SET title = lower(title);

// c'est ici que ça se passe
GET DIAGNOSTICS cnt := ROW_COUNT;

RETURN cnt;
END
$BODY$
LANGUAGE 'plpgsql' VOLATILE


Tags: PostgreSQL

mercredi 1 juillet 2009

Partager des librairies entre plusieurs projets

Publié par Infinite Loop, à 11 h 44 0 commentaire

Quand on possède un serveur de production qui héberge plusieurs projets web qu'on a nous-même développé, on a tendance à dupliquer les librairies d'un projet à l'autre, que ce soit le volumineux Zend Framework ou tout simplement des librairies JavaScript utiles comme jQuery ou Prototype.

Sans compter l'espace occupé par la duplication des fichiers, qu'arrive-t-il lorsque vient le temps de mettre à jour les versions ? On doit nécessairement appliquer les changements à chaque projet.

Il existe une façon de le faire d'un seul coup pour en faire bénéficier tout le monde en partageant les librairies. Mais ceci nécessitera quelques configurations au niveau du serveur Apache et de PHP.

  1. Dans le fichier de configuration d'Apache httpd.conf, assurez-vous que le module mod_alias soit activé :

    LoadModule alias_module modules/mod_alias.so

  2. Créez un alias :

    Linux :
    Alias /shared chemin/vers/répertoire/partagé/

    Windows :
    Alias /shared "D:/répertoire/partagé/"

    Lorsque le serveur reconnaîtra l'alias /shared, il résoudra automatiquement vers le chemin spécifié comme deuxième argument. Dans nos pages web, on pourra faire référence à une librairie comme ceci :

    <script type="text/javascript" src="shared/jquery/jquery-1.3.2.min.js"></script>
Jusqu'à maintenant, nous avons solutionné la première partie du problème. En effet, les deux premières étapes permettent de résoudre tout ce qui est statique (applicable aux fichiers JavaScript, images, etc). À partir d'ici, nous verrons comment résoudre ce qui se passe côté serveur.

Le truc : passer par un include path que nous attacherons automatiquement à tous nos fichiers grâce à l'instruction prepend file.
  1. Créer un fichier prepend.php qui contiendra les trois lignes suivantes :

    <?php
    $path = 'chemin/vers/librairies/php/';
    set_include_path(get_include_path() . PATH_SEPARATOR . $path);

    • Indiquez le chemin vers votre/vos librairie(s) à partager, par exemple le Zend Framework.
    • Ne fermez pas la balise PHP! Ceci évitera qu'un espace ou un saut de ligne se retrouve envoyé par erreur dans les headers de vos autres fichiers PHP.
    • Il est important d'utiliser get_include_path() pour conserver les anciens chemins définis ailleurs dans l'application, autrement nous écraserions la liste qui ne contiendrait que $path.

  2. Déposez le fichier prepend.php sur le serveur
  3. Maintenant, il faut donner l'instruction à PHP d'inclure prepend.php à chaque fois qu'un fichier PHP est appelé. Nous avons deux choix : soit l'inclure de façon globale dans php.ini, soit le mettre dans chaque projet par le fichier .htaccess.

    php.ini :
    auto_prepend_file /chemin/vers/prepend.php

    .htaccess :
    php_value auto_prepend_file /chemin/vers/prepend.php
À partir de maintenant, vous devriez être capable d'inclure des librairies PHP partagées. Par exemple, si votre répertoire partagé contient le Zend Framework, vous devriez pouvoir l'inclure comme s'il faisait réellement parti de votre projet :

require_once('Zend/Mail.php');

Pour être certain que tout fonctionne correctement, assurez-vous de bien tester cette configuration sur un serveur de développement.

Enfin, pour chaque composant, je vous recommande de toujours créer un répertoire /latest/ qui contiendra la version la plus récente de la librairie. Lorsque vous développerez, vous pourrez y référer plutôt qu'à une version spécifique et il sera beaucoup plus facile de mettre à jour tous vos sites en même temps.


Tags: Apache, PHP

Messages plus récents Messages plus anciens Accueil
S'abonner à : Messages (Atom)
    Suivre @code18 sur Twitter

    Catégories

    • Apache (21)
    • Citations (167)
    • Club Vidéo (24)
    • Coffre à outils (56)
    • CSS (8)
    • Curiosités (117)
    • Design Pattern (2)
    • Drupal (8)
    • Easter Eggs (22)
    • Extensions Firefox (20)
    • GIMP (7)
    • Histoire (21)
    • HTML (32)
    • Humour (57)
    • Intégration (34)
    • iPod (12)
    • JavaScript (110)
    • Jeu de combat (6)
    • Le coin du geek (128)
    • Liens (12)
    • Linux (56)
    • Livres (78)
    • Lois et principes (46)
    • Marché des saveurs (26)
    • Mathématique (18)
    • Mobile (5)
    • Montréal (32)
    • Musique (112)
    • Pancartes et écriteaux (16)
    • Perl (8)
    • Pérou (1)
    • PHP (130)
    • PostgreSQL (44)
    • Programmation (105)
    • Saviez-vous que (55)
    • Sécurité (22)
    • SEO (5)
    • SQL Server (22)
    • Vieilles publicités (6)
    • Virtualisation (8)
    • Voyages (1)
    • Zend Framework (26)

    Divers

    Archives

    • ►  2015 (6)
      • ►  août 2015 (1)
      • ►  juillet 2015 (1)
      • ►  février 2015 (3)
      • ►  janvier 2015 (1)
    • ►  2014 (8)
      • ►  décembre 2014 (1)
      • ►  novembre 2014 (1)
      • ►  octobre 2014 (1)
      • ►  août 2014 (2)
      • ►  juillet 2014 (2)
      • ►  janvier 2014 (1)
    • ►  2013 (53)
      • ►  décembre 2013 (2)
      • ►  novembre 2013 (1)
      • ►  octobre 2013 (3)
      • ►  septembre 2013 (2)
      • ►  août 2013 (5)
      • ►  juillet 2013 (3)
      • ►  juin 2013 (5)
      • ►  mai 2013 (3)
      • ►  avril 2013 (7)
      • ►  mars 2013 (7)
      • ►  février 2013 (11)
      • ►  janvier 2013 (4)
    • ►  2012 (105)
      • ►  décembre 2012 (8)
      • ►  novembre 2012 (5)
      • ►  octobre 2012 (4)
      • ►  septembre 2012 (1)
      • ►  août 2012 (8)
      • ►  juillet 2012 (7)
      • ►  juin 2012 (7)
      • ►  mai 2012 (10)
      • ►  avril 2012 (13)
      • ►  mars 2012 (15)
      • ►  février 2012 (15)
      • ►  janvier 2012 (12)
    • ►  2011 (146)
      • ►  décembre 2011 (14)
      • ►  novembre 2011 (11)
      • ►  octobre 2011 (12)
      • ►  septembre 2011 (13)
      • ►  août 2011 (15)
      • ►  juillet 2011 (17)
      • ►  juin 2011 (18)
      • ►  mai 2011 (15)
      • ►  avril 2011 (9)
      • ►  mars 2011 (7)
      • ►  février 2011 (3)
      • ►  janvier 2011 (12)
    • ►  2010 (398)
      • ►  décembre 2010 (29)
      • ►  novembre 2010 (28)
      • ►  octobre 2010 (32)
      • ►  septembre 2010 (34)
      • ►  août 2010 (22)
      • ►  juillet 2010 (35)
      • ►  juin 2010 (42)
      • ►  mai 2010 (36)
      • ►  avril 2010 (37)
      • ►  mars 2010 (34)
      • ►  février 2010 (32)
      • ►  janvier 2010 (37)
    • ▼  2009 (430)
      • ►  décembre 2009 (32)
      • ►  novembre 2009 (34)
      • ►  octobre 2009 (33)
      • ►  septembre 2009 (37)
      • ►  août 2009 (37)
      • ▼  juillet 2009 (39)
        • SQL Serveur 2008 perd le mot de passe ?
        • Regex greedy vs. lazy
        • White & Nerdy de Weird Al Yankovic
        • Bing remplacera le moteur de Yahoo!
        • Festival Geek de Montréal
        • Compter le nombre de lignes d'un fichier
        • Choix de mot de passe
        • Compresser des archives avec PHP
        • Citation no. 40 sur l'imagination
        • Algorithme de Luhn (mod10) pour cartes de crédit
        • Opérations sur un champ texte dans MSSQL
        • Plugin jQuery Uploadify 2.0.0
        • Nouveau easter egg dans Google
        • Option noConflict de jQuery
        • Gros bon sens pour l'usage des courriels
        • Équivalent de nslookup en PHP
        • Parkinson en milieu de travail
        • Performance JavaScript
        • Citation no. 39 sur l'imbécilité
        • Créer un singleton en JavaScript
        • Compiler un programme en C++
        • Virus Newton
        • Installer browscap.ini pour PHP
        • Qui se souvient du VRML ?
        • Star Wars et Telnet
        • Installer Telnet pour Windows 7 et Vista
        • Citation no. 38 sur la perfection
        • Internet Explorer et les messages simplifiés
        • Désactiver un trigger sous SQL Server
        • Impression avec saut de page en CSS
        • Trucs pour inverser la valeur d'un booléen
        • Principe : Fake It
        • Exécution avec des backticks en PHP
        • Ne volez pas cette regex de courriel !
        • Citation no. 37 sur le doute
        • Instruction GOTO de PHP 5.3
        • Cacher un fichier dans une image
        • Obtenir le statut d'exécution d'une requête Postgr...
        • Partager des librairies entre plusieurs projets
      • ►  juin 2009 (38)
      • ►  mai 2009 (37)
      • ►  avril 2009 (35)
      • ►  mars 2009 (37)
      • ►  février 2009 (32)
      • ►  janvier 2009 (39)
    • ►  2008 (84)
      • ►  décembre 2008 (34)
      • ►  novembre 2008 (39)
      • ►  octobre 2008 (11)

    Abonnés

Copyright © All Rights Reserved. Code 18 | Converted into Blogger Templates by Theme Craft