12/20/2008

Retrouver le chemin XPath d'un élément html via Javascript

Après de nombreuses recherches mais en vain, j'ai décidé de coder cette fonction qui permet de retourner le chemin XPath d'un élément html.

//@el élément HTML
function getXpath(el){

XPath = '/'+el.nodeName
+ (el.id?'[@id=\''+ el.id +'\']':(el.className?'[@class=\''+ el.className+'\']':''));

while(el.parentNode && el.parentNode.nodeName !== '#document')//on monte d'un élément à chaque itération
{
el = el.parentNode;
XPath = '/'
+ el.nodeName
+ (el.id?'[@id=\''+ el.id +'\']':(el.className?'[@class=\''+ el.className+'\']':''))
+ XPath;
}

return XPath.toLowerCase();
}

Si vous souhaitez retourner uniquement le chemin XPath de l'élément père, il suffit de remplacer cette ligne :

XPath = '/'+el.nodeName
+ (el.id?'[@id=\''+ el.id +'\']':(el.className?'[@class=\''+ el.className+'\']':''));

Par :

XPath = '';

 

Exemple d'utilisation pour une div ayant une valorisation de l'ID à post-845 :

alert(getXpath(document.getElementById('post-845')));
//retourne par exemple : /html/body/div/div[@id='page']/div[@id='content']/div[@id='post-845']

Testé sous Firefox 3, Chrome, IE7, IE8. Tout les chemins retournés jusqu'à présent ont été valide mais il est possible d'affiner la précision en spécifiant l'index de l'élément. C'est utile lorsque, par exemple, il existe plusieurs éléments enfants de même type pour un unique élément parent.

12/12/2008

Création d’un keygen (générateur de clés) à partir d’un algorithme

Il y a quelques jours, j’ai travaillé sur la sécurité d’une application web. Cette dernière demandait à l’utilisateur de payer une licence afin de faire disparaitre le texte “version demo”. Je montrerai le travail de recherche et d’analyse du code PHP et Javascript la semaine prochaine, pour le moment intéressons nous à la création d’un keygen (générateur de clé) à partir d’un algorithme donné. Je précise une fois de plus que cet article a pour but de faire “découvrir” une petite partie de la “sécurité informatique” et non d’inciter au piratage.

 

Rappel sur les keygens :

Un générateur de clés, aussi appelé keygenerator ou tout simplement keygen, est un logiciel générant des numéros de série afin d'installer/déverrouiller/lancer une application.

Un générateur de clés a deux moyens pour trouver une clé-cd valide : la méthode brute force et la méthode qui consiste à reconstituer l'algorithme utilisé par la société éditrice du logiciel.

Source Wikipedia

J’en profite aussi pour préciser les expressions algorithmiques utilisées dans cet article :

  • POS(X) : retourne le caractère à la position X, en partant de 0, d’une string quelconque.
  • X MOD Y : retourne X modulo Y
  • LEN(STR) : retourne la longueur d’une string

Les postulats sur lesquels nous nous baserons :

  • On se basera sur la string DK suivante (si quelqu’un connait le nom technique je suis intéressé) : 123456789ABCDEFGHJKLMNPQRSTUVWXYZ
  • La clé (licence key) que doit entrer l’utilisateur est de 11 caractères ou plus.
  • Nous comptons, pour les positions de caractère par exemple, à partir de 0.

Une fois la clé de licence spécifiée, le programme va effectuer les traitements suivants afin de définir la validité d’une clé :

  • Création d’une seconde clé (clé temporaire/intermédiaire à partir de la clé de licence entrée par l’utilisateur) sous la forme : [11][0][8][12]
    • [11] est la caractère en 11ème position de la licence originale
    • Si la licence originale est ZK5JC9EO6IEGP alors la clé intermédiaire sera GZ6P
  • On vérifie à partir de cette clé intermédiaire que :
    • Le modulo de la position du second caractère sur DK est différent de 1. On trouvera alors [0] c’est à dire le caractère en 0ème position de notre clé de licence finale.
      • Par exemple pour 12 :
      • 12 MOD 5 = 2 //12 est valide (modulo différent de 1) on cherche donc le caractère correspondant
        POS(12) = C //C est donc un caractère possible en position 1 pour notre clé intermédiaire et en position 0 pour notre clé finale
        [0] = C
    • On prends aléatoirement les positions des 0ème et 2ème caractères sur DK
    • La position du 3ème caractère doit être égale à (j'ai décomposé le code pour une lecture plus aisée) :
      • X = POS([11]) + POS([8]) //on additionne les positions sur DK de 0ème et 3ème caractère
        X *= 9
        X = X Mod (Len(DK) - 1) //on repositionne X sur DK
        [12] = POS(X) //le 3ème caractère de notre clé intermédiaire est donc à la position X sur DK

L’idée est donc de générer aléatoirement des licences qui correspondent à cet algorithme. Voici un code VB6 permettant de résoudre cette problématique :

Randomize '(re)initialisation du moteur de nombre aléatoire
Dim dK as String
dK = "123456789ABCDEFGHJKLMNPQRSTUVWXYZ"
Dim sr(12) As String 'clé de licence finale que nous allons générer

'#########################################
' Traitement sur la clé intermédiaire
'#########################################

Dim tmp0, tmp1, tmp2, tmp3 As Integer

'Recherche du 2ème caractère
tmp = 1
Do While ((tmp Mod 5) = 1)
tmp = rand(1, Len(dK))
Loop
sr(1) = Mid(dK, tmp, 1)

'On créé le 0ème & 2ème caractère
tmp0 = rand(0, Len(dK) - 1)
tmp2 = rand(0, Len(dK) - 1)

sr(0) = Mid(dK, tmp0 + 1, 1)
sr(2) = Mid(dK, tmp2 + 1, 1)

'Le 3ème caractère doit être égal à
tmp3 = tmp0 + tmp2
tmp3 = tmp3 * 9
tmp3 = tmp3 Mod (Len(dK) - 1)
sr(3) = Mid(dK, tmp3 + 1, 1)

'#########################################
' On en déduit ensuite la clé finale
'#########################################

'Ordre : [11][0][8][12]
sr(11) = sr(0)
sr(0) = sr(1)
sr(8) = sr(2)
sr(12) = sr(3)

sr(1) = Mid(dK, rand(1, Len(dK)), 1)
sr(2) = Mid(dK, rand(1, Len(dK)), 1)
sr(3) = Mid(dK, rand(1, Len(dK)), 1)
sr(4) = Mid(dK, rand(1, Len(dK)), 1)
sr(5) = Mid(dK, rand(1, Len(dK)), 1)
sr(6) = Mid(dK, rand(1, Len(dK)), 1)
sr(7) = Mid(dK, rand(1, Len(dK)), 1)
sr(9) = Mid(dK, rand(1, Len(dK)), 1)
sr(10) = Mid(dK, rand(1, Len(dK)), 1)
'La clé finale = Join(sr, "")

J’utilise des variables intermédiaires et de nombreux appelles à la fonction rand. Ce code est très facilement optimisable mais j’ai préféré le décomposer afin de faire ressortir l’algorithme de base et pour que cet article soit accessible au plus grand nombre.

Si vous avez aimé cet article ou si vous avez des demandes particulières, n’hésitez pas à le faire savoir en commentaire. N’oubliez pas de vous inscrire au flux rss du blog :).

12/04/2008

Un jeu caché (easter-egg) sur le site de Jquery ?

En "triffouillant" un peu sur le site de JQuery, j'ai découvert ces quelques lignes :

// Hehe.
if ( window.addEventListener ) {
var kkeys = [], konami = "38,38,40,40,37,39,37,39,66,65";
window.addEventListener("keydown", function(e){
kkeys.push( e.keyCode );
if ( kkeys.toString().indexOf( konami ) >= 0 )
window.location = "http://ejohn.org/apps/hero/";
}, true);
}

On voit donc que :

  1. Le script enregistre toutes les touches pressées au clavier dans un tableau kkeys 
  2. Il vérifie à chaque fois si la combinaison de touche contenu dans konami à été saisie ou non, et si c'est le cas, la page est redirigée vers le jeu.

jquery-logo

Si vous êtes de ceux qui préfère tester ce easter-egg plutôt que d'entrer directement l'adresse dans votre navigateur, il vous suffit d'appuyer sur les touches de votre clavier dans cet ordre depuis le site de JQuery :

  • 2x flèche haut
  • 2x flèche bas
  • flèche gauche
  • flèche droite
  • flèche gauche
  • flèche droite
  • b
  • a

Et voila !

Pour ma part je connaissais déjà ce Guitar Hero Like de John Resig (qui est le fondateur de JQuery) mais je dois avouer que j'ai été surpris par ces quelques lignes de code.

11/25/2008

Amusons-nous avec Sébastien Chabal (…ou comment “profiter” du buzz d’Orange)

Logo OrangeVous le savez peut-être, Orange vient de lancer une campagne marketing au doux nom de Chabal Le Duel. Visitez-donc le site si vous ne connaissez pas. L’idée est vraiment excellente : recevoir un appel personnalisé de Sébastien Chabal qui vous demande de l’aide pour marquer un but. En plus l’impression de réelle est augmentée par la synchronisation entre le mini-film que vous voyez à l’écran et ce qui se dit dans votre téléphone.

Avertissement : Je vois fleurir ce type de site (appel téléphonique + vidéo) depuis un bon moment. Cet article n’est que le résultat d’une (petite) réflexion que je me suis permis de me poser il y à maintenant 30 minutes. Mon but est de montrer comment il est possible de “dévier” (légèrement) l’utilisation d’une telle plateforme et en aucun cas de réaliser des actions malhonnêtes, je vous demanderai donc d’en faire autant.

 

Oui et alors ?

Alors je me suis intéressé un peu plus aux échanges client(flash)/serveur. Une fois le formulaire (où l’on doit remplir son nom, prénom, email et numéro de téléphone) envoyé ces échanges se forment et voici un résumé :

#request# GET http://as00.estara.com/OneCC/200106295512/checkPhone.php?phone1=336XXXXXXXX

(Hypothèse) : “vérification si le numéro de téléphone est correcte”, retourne le nombre d’appels envoyés vers ce téléphone par la plateforme.

 

#request# POST http://as00.estara.com/OneCC/200106295512/email.php (+ paramètres)

(Hypothèse) : page pour l’enregistrement de l'email, nom, prénom, numéro de téléphone et options diverses.

 

#request# POST http://as00.estara.com/OneCC/200106295512/mpc2.php

Paramètres :

phone1=336XXXXXXXX Numéro de téléphone au format international
&ord=0%2F5684821980666167
&name=FRANCOIS Prénom à utiliser

Ce script permet d'établir l'appel avec le numéro précisé et de spécifier le prénom que le Chabal virtuel devra employer.

Retourne :

STATUS_URL=http://paetec-2901.estara.com/vxml/contact/status.php?confid=e56978910e2936d11fae5ca9d5hh5bv6
DISCONNECT_URL=http://paetec-2901.estara.com/vxml/contact/disconnect.php?confid=e56978910e2936d11fae5ca9d5hh5bv6

 

Puis, pour garder la synchronisation entre le téléphone et la vidéo, il y a un appel récurrent de :

#request# POST http://paetec-2601.estara.com/vxml/contact/status.php

Paramètres :

nbrequest=1
&confid=e56978910e2936d11fae5ca9d5hh5bv6
&ord=0%2F5684821980666167

 

Constat après quelques tests

  • La variable ord peut être vide lors de l’appel de mpc2.php la communication avec le téléphone sera quand même effectuée
  • Si name n’est pas  dans la liste pré-enregistrée, ou s’il n’est pas défini, le Chabal virtuel dira “salut l’ami”
  • Si ord n’est pas défini, alors l’appel ne sera plus en mode inconnu mais par un numéro en 01…

Il est donc tout à fait possible d’effectuer directement une requête POST sur mpc2.php afin de lancer un appel vers un numéro de téléphone prédéfini.

 

Quels déviances sont possibles ?

Sachant ce que l’on sait maintenant il nous est possible de détourner ce système de son utilisation principale, on pourrait donc :

  • Flooder un ami…ou enemi
  • Créer un bash ou un programme qui appelle, via Curl ou autre, à intervalle régulier, via un cron par exemple, le script mpc2.php. Ce qui pourrait permettre en pratique de faire téléphoner Chabal à minuit tout les soirs à un “amis”.
  • …et sans doute d’autres détournements dont je n’ai pas l’idée à l’heure où j’écris ces lignes.

Beaucoup trop de site “full flash”, en plus du fait qu’ils ne sont vraiment pas agréable et lent (point de vue personnel) oublient l’aspect de sécurisation des données qui transitent, un simple chiffrage des valeurs serait déjà mieux.

11/22/2008

[Mini-Projet VB6] Machine à sous - Jackpot

Dans le cadre d’un cours de VB6 à l’EPSI Nantes, il nous a été demandé de créer une machine à sous en VB6.
Le cahier des charges était le suivant :
  • Au démarrage l’utilisateur entre la somme à versée en banque
  • 3 libellées qui feront défiler des chiffres de 1 à 9
  • L’utilisateur choisit sa mise
    • 7x1 : on gagne 5 fois la mise
    • 7x2 : on gagne 10 fois la mise
    • 7x3 : on gagne 100 fois la mise
    • Aucun 7 : on perds la mise
  • Afficher le taux de réussite
  • Lorsque l’utilisateur perds, si son taux de réussite est supérieur à 25% on lui propose d’enregistrer son score
Mini-projet VB6 JackPot - Machine à sous
Interface du jeu une fois lancé
Mini-projet VB6 JackPot - Machine à sous
Ici aucun 7, on perds donc la mise.
En réalité, j’ai d’abord réalisé une version répondant exactement au cahier des charges lors du cours. La version que je vous propose ici est un peu plus “fantaisiste” et comme vous pouvez le voir j’en ai profité pour me remettre à Photoshop. L’installeur du mini-projet peut être téléchargé ici, d’autres captures sont disponibles sur mon flickr.
11/21/2008

Activer les fonctionnalités cachées de Windows Seven build 6801

Continuons sur notre lancée à la découverte de Windows Seven. Aujourd’hui voyons comment débloquez en un clic les fonctions de multitouch, diaporama d’arrière plan (slideshow wallpapers) et bien plus. Cependant avant d’appliquer ce patch sauvegardez les fichiers suivant :

\Windows\Explorer.exe
\Windows\System32\wisptis.exe
\Windows\System32\ieframe.dll
\Windows\System32\shell32.dll
\Windows\System32\stobject.dll
\Windows\System32\TabletPC.cpl
\Windows\System32\themecpl.dll
\Windows\System32\themeui.dll
\Windows\System32\powercfg.cpl

Ensuite téléchargez le patch pour architecture x86. La version pour x64 serait disponible demain.

Patch blue badge Arrière plan aléatoire via flux rss (flickr ici) Option du multitouch

Pour plus de capture rendez-vous sur mon Flickr.

11/09/2008

Comment débloquer la nouvelle barre de tâche de Windows Seven

Présentée lors de la dernière PDC, la nouvelle barre de tâche de Windows Seven a de quoi intriguer. Seulement, Microsoft a annoncer qu’elle ne serait pas présente dans les différentes versions données aux développeurs lors de la conférence du fait de son instabilité.

Cependant Rafael de WithinWindows déjà connu pour ses patchs Uxtheme nous propose une manipulation pour activer cette fonctionnalité.

  1. Téléchargez d’abord le zip suivant votre plateforme x86 ou x64 que vous devrez extraire dans le dossier windows.
  2. Ouvrez ensuite une console en mode Administrateur et exécutez les commandes suivante :
    • takeown /f %windir%\explorer.exe
    • cacls %windir%\explorer.exe /E /G %username%:F (remplacez “username” par votre nom d’utilisateur)
    • taskkill /im explorer.exe /f
    • cd %windir%
    • start unlockProtectedFeatures.exe

Ayant moi même réalisé la manipulation, j’ai rencontré un problème au niveau des commandes takeown et cacls, si vous rencontrez les mêmes difficultés :

  • Clic droit sur “explorer.exe”
  • Onglet sécurité
  • Ajoutez-vous dans la liste des utilisateurs et vérifiez bien que vous avez coché toutes les propriétés

Via.

11/07/2008

Mon test de Windows Seven M3 Build 6801

Voici quelques captures d’écrans de Windows Seven Milestone 3 Build 6801 (flickr) réalisées lors de mon test. N’hésitez pas à afficher les informations complémentaires lors de la visualisation du diaporama.

 

 

Il s’agit d’une Milestone donc il ne faut en tirer aucune conclusion, on se souviendra de Longhorn lors d’une précédente PDC et sa différence avec Vista. Mais pour le moment, j’en retiens une certaine stabilité, un réel progrès pour ce qui est de l’utilisation mémoire ainsi que du temps de démarrage (qui sont les principaux objectifs de Microsoft).

10/24/2008

Comparaison entre DomainR et DomainFinder

Vous l’avez peut-être vu, un nouveau service vient de voir le jour sur internet : DomainR. Il fait exactement la même chose que DomainFinder et c’est d’ailleurs cela qui me chagrine un peu. Le minimum quand on reprends l’idée de quelqu’un d’autre c’est de l’améliorer, surtout quand cette idée est assez originale. C’est donc pour cela que j’ai décider de faire un petit comparatif entre ces deux services, ceci, bien entendu dans la plus grande objectivité possible (du moins je vais essayer).

Le nom

En effet, Domainr est déjà un nom plus “tendance” pour un service de ce genre. Et c’est un fait, DomainFinder est un nom que j’ai du trouvé dans l’empressement, ce qui m’intéressai à la réalisation de ce projet était les fonctionnalités que j’allais y mettre et non ce qu’on en percevrait au premier regard c’est à dire le nom et le design.

Le design

Lorsque j’ai découvert DomainR, c’est la première chose qui m’à frapper, une simple textbox, aucun bouton, un texte descriptif et un logo. Simple et clair c’est l’essence même d’un service web 2.0. C’était bel et bien mon idée initiale à la création de DomainFinder mais quand je le regarde maintenant je me dit qu’il y a beaucoup trop d’informations complémentaires. Le footer de DomainFinder n’est pas assez clair, trop brouillon, contenant des éléments de tailles différentes. L’utilisation de cadres pour séparer les zones à l’écran et leurs dispersions (en haut à gauche, en haut à droite, au milieu, en bas à gauche et en bas à droite) empêche l’utilisateur d’avoir une vision globale de la page.

DomainR image

DomainR - DomainFinder

Le concept

Pour le moment DomainR est une simple copie du concept de DomainFinder, l’utilisateur propose un mot, une expression, et le service cherche les domaines, sous domaine correspondant.

Les fonctionnalités

  • La vérification de disponibilité des domaines : sur une même expression, par exemple “francois guillaume”, DomainFinder indique la disponibilité de chaque domaine alors que DomainR n’informe que pour 2 domaines.
  • Le nombre de résultat : DomainFinder fourni l’intégralité des possibilités ce qui n’est pas le cas de DomainR (voir capture). Ainsi sur l’expression “let’s rock”, DomainR donne 4 résultats et DomainFinder 10.
  • Les extras : DomainFinder permet à l’utilisateur de recevoir par email les résultats de sa recherche, DomainR permet d’avoir des informations supplémentaires sur le TLD (Top Level Domain) via des sites extérieurs.

En pratique

Après 6 requêtes sur les deux services, DomainFinder fourni deux fois plus de résultat et indique 33% de domaines valides (ou non) en plus.

comparaison_en_nombre_de_résultat_par_requête comparaison_en_nombre_de_validation_de_domaine

Le document recueillant les différents tests est disponible sur Google Document pour les intéressés. Certains diront que seulement 6 tests ne permettent pas d’avoir une bonne idée et c’est tout à fait vrai. Mais en vu des premiers résultats, je ne pense pas que DomainR puissent avoir une quelconque chance (en terme de résultat j’entends) contre DomainFinder.

10/15/2008

Récupérer une photo Flickr protégée

Logo flickrAvertissement : La méthode que je présente ici n’est à utiliser que si les photos vous appartiennent et que vous avez perdu vos identifiants Flickr.

 

Vous l’avez peut-être remarqué, il est “impossible” de récupérer certaines photos sous Flickr en effectuant un clic droit puis Enregistrer l’image sous…. Vous obtiendrez alors une image transparente.

Pourquoi ? L’idée pour “protéger” une photo est de lui superposer une autre image de même taille et transparente (ou un filigrane). Ainsi la majorité des utilisateurs ne pourrons pas enregistrer l’image. Cette technique est aussi utilisée par les sites de vente de fonds d’écrans pour téléphone portable et bien d’autre à vous de voir lequel.

Donc, il suffit simplement d’enlever l’image de “protection” pour pouvoir atteindre le saint graal. Pour cela, j’aurai pu créer un bookmarklet pour Flickr, mais quid des autres sites ? Donc je vais simplement donner une des manipulations possibles et qui me semble la plus rapide.

 

Allez par exemple sur cette page Flickr qui contient une photo protégée, puis :

  • Ouvrez Firebug
  • Inspecter
  • Clic sur la photo que vous souhaitez “déprotéger”
  • Clic droit sur la partie de code html qui à été surlignée dans Firebug
  • Supprimer l’élément
  • Fermez firebug
  • Maintenant vous pouvez enregistrer l’image, ou simplement l’afficher séparément.
10/01/2008

Algorithme et code C d’une fonction de tri croissante

Dans le cadre d’un cours de C à l’EPSI Nantes, il nous a été demandé de créer une fonction qui permettra de trier de façon croissante (ou décroissante, c’est simplement l’algorithme inverse) une série de 5 nombres entrée par l’utilisateur. Il est à noter que la fonction ne pourra pas utiliser de tableau, ni de pointeur, ni les fonctions de tris disponibles en C.

Je vais donc vous proposer dans cet article un des algorithmes possible pour répondre à cette problématique.

procedure tri
   E: entier : x1,x2,x3,x4,x5;
debut
   Si x1 > x2 Alors
      tri(x2,x1,x3,x4,x5)
   SinonSi x2 > x3
      tri(x1,x3,x2,x4,x5)
   SinonSi (x3 > x4)
      tri(x1,x2,x4,x3,x5)
   SinonSi (x4 > x5)
      tri(x1,x2,x3,x5,x4)
   FinSinonSi
   //Test si x1 > x2 et x2 > x3 ...
   //Afficher les nombres dans le bon ordre

Et le code C :

void tri(float x1, float x2, float x3, float x4, float x5){

   if(x1 > x2)
      tri(x2,x1,x3,x4,x5);
   else if(x2 > x3)
      tri(x1,x3,x2,x4,x5);
   else if(x3 > x4)
      tri(x1,x2,x4,x3,x5);
   else if(x4 > x5)
      tri(x1,x2,x3,x5,x4);
   //Test si x1 > x2 et x2 > x3 ...
   //Afficher les nombres dans le bon ordre

Il est alors facilement imaginable d’améliorer l’algorithme : avec un nombre x d’entier ou de réel au lieu de 5, d’utiliser un tableau et des pointeurs.

8/20/2008

Mise à jour de PlurkCounter et du Widget Karma Plurk

Petite note de service pour vous informer que PlurkCounter et le widget Karma n'était plus fonctionnel depuis un certain temps. Dès constatation du problème une mise à jour à été effectuée afin de corriger l'erreur (qui était dû à une mise à jour de Plurk) les services sont donc à nouveaux opérationnelles.

8/08/2008

Regarder les Jeux Olympiques en live via internet

Si comme moi vous souhaitez regarder les JO pendant vos vacances (ou plus précisément au travail) vous serez content d'apprendre que France Télévision à pensé à nous !

La page du flux live du Direct des Jeux Olympique existe en deux versions, l'une en silverlight (vive les interfaces riches) et l'autre incorpore un simple lecteur.

Sinon vous pouvez accéder directement au flux live à cette adresse.
7/29/2008

Le CrossDomain, un besoin de support natif pour nos futurs applications web

Pour ceux qui ne le savent pas, le CrossDomain est l'appellation que l'on donne à un script (qui peut être Javascript ou autre) lorsque celui-ci effectue des requêtes HTTP vers d'autres domaines différents de celui qui l'héberge.

 

Actuellement les navigateurs modernes n'autorisent pas les scripts Javascript à effectuer des requêtes sur d'autres domaines principalement pour des raisons de sécurité. Cependant, l'équipe en charge du développement du navigateur Mozilla Firefox à annoncée récemment que la prochaine version permettrait le CrossDomain ce qui est déjà le cas (dans une moindre mesure) d'Internet Explorer 8 Beta.

 

Comment les développeurs de navigateur vont-ils faire pour garder un niveau de sécurité suffisant ?

A mon humble avis, à chaque fois qu'un script voudra effectuer une requête sur un autre domaine que celui du script, l'utilisateur se verra informer de la validation ou non de la requête. Il est d'ailleurs à prévoir qu'il sera permis à l'utilisateur de mettre en place des listes "blanche" et des listes "noires" afin d'autoriser (ou non) les scripts d'un domaine à effectuer des requêtes sur un autre.

Mais cela entraînera indéniablement d'énormes failles de sécurités. En effet, dès qu'un utilisateur aura mis un domaine sur liste blanche. Prenons l'exemple du domaine free.fr. Si l'utilisateur ajoute ce domaine dans sa liste blanche au lieu de mettre le domaine xxxxxxxx.free.fr alors théoriquement tous les sites personnels hébergés chez free pourront effectuer du CrossDomain, c'est à dire le meilleur comme le pire.

Un autre exemple, il sera possible pour un site malveillant d'accéder directement à votre compte Google ou à votre boite email Gmail (pour récupérer votre liste de contact) ceci dans l'hypothèse ou vous seriez déjà connecté à ces services. Nous étudierons la faisabilité de ce cas précis dès la sortie de la version final de Firefox ainsi que d'Internet Explorer 8.

 

Les techniques actuelles pour effectuer du CrossDomain

Les développeurs web on accès à généralement 3 techniques pour effectuer du CrossDomain dans leurs applications et scripts :

  • Le proxy : Votre script client (javascript) appelle un script serveur (Php, Asp, Ruby) qui va lui même effectuer la requête sur le serveur distant et qui pourra retourner le résultat de cette requête à votre script client. Cette technique est notamment utilisée par Netvibes pour récupérer les flux rss des domaines distants. L'avantage de cette technique est de pouvoir mettre en place un système de cache du côté serveur ce qui permet dans la plupart des cas une amélioration notable des performances de l'application.
  • Le script (JSON) : A chaque données que l'on souhaite échanger avec le serveur on ajoute une balise "<script>" dont le script source se trouve sur un domaine distant et avec diverses paramètres. Le script serveur distant pourra alors retourner sous différents formats les informations demandées (soit en Json si il s'agit de donné ou simplement un fonction Javascript)  au script client. Il est même possible d'exécuter une fonction de callback dès que les données sont chargées.
  • L'image : Contrairement aux deux techniques précédentes, l'information est unilatéral c'est à dire qu'elle va du script client vers le domaine extérieur. En script serveur est mis en place sur le domaine distant et est capable de traiter les informations passées en paramètre (par exemple : http://domaine-distant.ndd/monimage.php?valeur1=bonjour) à la fin de son exécution il retournera une image transparente ou de petite taille. Ainsi le script client, en modifiant l'adresse de cette image pourra envoyer des informations au serveur distant. Cette technique est utilisée par la majorité des systèmes de statistique (Xiti, Google Analytics, ...).
  • La modification des préférences du navigateur : sous Firefox il est possible d'autoriser définitivement les requêtes HTTP (Ajax) entre plusieurs domaines via la commande javascript : user_pref("capability.policy.default.XMLHttpRequest.open","allAccess"); cependant il faudra que l'utilisateur final configure de la même manière son propre navigateur. Cette technique est donc conseillée seulement dans le cas d'un intranet d'entreprise sans connexion avec l'extérieur (internet).

 

Mot de fin

Le support ou non du CrossDomain en natif pour les navigateurs inclus des problèmes de sécurité inhérent au développement d'application web (XSS par exemple). Il faudra donc suivre de très près l'évolution des discussions sur ce sujet.

7/16/2008

Priston Tale 2 débarque en Europe, premières images exclusive !

Pour ceux qui ne le savent pas, Priston Tale 2 (PT2), The Second Enigma est un MMORPG crée par Yedang Online et distribué en Europe par Key To Play qui est très attendu par la communauté européenne de joueur. En effet, alors que Priston Tale 1 n'était disponible seulement en Corée (les chanceux) PT2 arrive pour les joueurs Européens. Au programme, un nouveau moteur graphique (basé sur l'excellent Unreal Engine) et une nouvelle stratégie de combat ainsi que bien d'autres nouveautés dont nous n'avons pas encore connaissance.

Synopsis :

L’action se situe peu après que le Dieu démon Midranda ait été vaincu et exilé par les héros de Priston Tale grâce à une armée légendaire au pouvoir assez puissant pour vaincre, ne serait-ce qu’une fois. A présent l’armée de Midranda s’est décuplée et attend sa résurrection sans trouver d’ennemi assez fort nulle part ailleurs, les espoirs et la vie du monde entier tiennent à un fil. Néanmoins, une rumeur arrive des terres lointaines, il semblerait qu’une armée nommée “enigma” pourrait vaincre Midranda et ses armées, mais il faut absolument la retrouver à temps. Le dernier espoir du monde est donc entre les mains de nos héros. Trouveront-ils la deuxième énigme à temps ?

Quelques images du jeu :

IMG1 IMG2 IMG3 IMG4

Il semble que le jeu sera disponible à la vente dès septembre mais aucune date de lancement ni de bêta-test n'a été communiquée. Ouvrez l’oeil (pixels dissimulés), le site teaser www.pt2europe.com vous révélera des contenus exclusifs du jeu...

Merci à BuzzParadise de m'avoir proposé cette campagne, juste publié déjà premier sur Google Blog.

7/11/2008

Astuce (bookmarklet) Plurk pour activer tous les "mute"

Je ne sais pas vous, mais j'aime de plus en plus Plurk. La différence avec Twitter est réellement profonde bien qu'il manque quelques petites choses... Comme par exemple une fonction "mute all". En effet, sur chaque Plurk il est possible de désactiver les notifications sur les réponses relatives à ce Plurk.

Le problème une fois que vous avez beaucoup d'amis c'est qu'ils écrivent beaucoup et vous n'avez pas forcément envie, lors de votre connexion, de suivre les réponses aux précédents Plurk. C'est pour cela que j'ai l'honneur de vous présenter le bookmarklet ultime de tout bon Plurkien à savoir Mute All.

Mute All, une fois dans votre barre de favoris vas, en un clic, passer tout les Plurks actuellement sous vos yeux en "mute" ce qui veut dire que vous ne suivrez pas leurs réponses.

Si vous souhaitez utiliser Mute All, il vous suffit de déplacer ce lien [ Mute All ] dans votre barre de favoris.

Maintenant le côté technique, pour réaliser ce bookmarklet, je ne souhaitait pas charger JQuery (comme je l'avais fait afin de créer le bookmarklet pour ajouter une signature HTML sous Gmail) mais il me fallait la fonction getElementsByClassName mais une version qui soit compatible avec la majorité des navigateurs. Après une recherche, j'ai trouvé une fonction écrite par Robert Nyman (enfin une fonction que je n'ai pas eu besoin d'améliorer !) qui supporte l'appel multi-classe et qui permet de fonctionner sous Internet Explorer.

Voici donc un extrait du code de Mute All :

tnew = getElementsByClassName('plurk','div');
cm = tnew.length;
for(i=0;i<cm;i++)
{
    if(tnew[i])
    {
        tnew[i].onmouseover();
        tmute = getElementsByClassName('mute delete','a',tnew[i]);
        if(tmute[0] && tmute[0].className.indexOf('unmute') == '-1')
        {
            tmute[0].onclick();
        }
        tnew[i].onmouseout();
    }
}

Voici l'algorithme simplifié :

  1. On récupère tout les Plurks qui ont la classe "plurk"
  2. On les survoles afin d'activer/afficher le lien "mute"
  3. On vérifie que ce lien est bien un lien "mute" et non un lien "unmute"
    1. Si le lien est un lien "mute" alors
      1. On clic sur ce lien.
  4. On désactive le survole sur le Plurk.

Et voila !

7/06/2008

Rétro-ingénierie (reverse-engineering) : Possible algorithme de Tinyurl, minurl et autre Tinyurl-like

Je suis actuellement en train de développer une application Adobe Air comme certains le savent, et j'ai besoin (ou plutôt envie) de créer moi aussi mon propre "raccourcisseur" d'url.

Apparemment la plupart des services du genre se base sur une base de données, l'objectif pour être concurrentiel est donc d'effectuer le moins de requête possible afin que le service soit le plus rapide. Après avoir soumis à la suite plusieurs urls différentes à minurl.fr, j'ai obtenu cette suite d'url :

  • http://minurl.fr/12
  • http://minurl.fr/13
  • http://minurl.fr/14
  • http://minurl.fr/15
  • http://minurl.fr/16
  • http://minurl.fr/17

Que peut-on en conclure ?

  1. A chaque nouvelle url qui n'existe pas dans la base de données
    1. On créé un identifiant, supérieur au dernier identifiant, que l'ont lie à l'url (ou plutôt un équivalent compressé de l'url).
      1. Donc dans la table de notre base de données on à pour le moment les champs suivant :
        1. id varchar(10) (primary) : identifiant pour l'url qui sera afficher
        2. url varchar(40) (index) : champs pour l'url compressée
          1. Il est préférable que le contenu de ce champs soit compressé si l'on ne veut pas une énorme base de données mais cela n'est pas obligatoire !
          2. Dans cette exemple d'algorithme nous ne nous soucierons pas de la compression de l'url.
  2. Si le script reçoit un identifiant
    1. Chercher dans la base de données si l'id existe
      1. Il existe : on retourne l'url (il faudra la décompresser si on l'a compressée)
        1. On redirige vers cette url.
      2. Il n'existe pas : on informe l'utilisateur.
  3. Si le script ne reçoit pas d'identifiant
    1. On propose le formulaire d'ajout

 

Maintenant, on répète l'expérience avec Tinyurl, on à donc cette suite d'url :

  • http://tinyurl.com/6l74df
  • http://tinyurl.com/6d8r75
  • http://tinyurl.com/5o5c7d
  • http://tinyurl.com/5tfegj
  • http://tinyurl.com/63kjqo
  • http://tinyurl.com/6ys8ym

Que peut-on en conclure ?

  1. Il semble que Tinyurl utilise un système de création d'ID aléatoire, ce qui empêche toute prédiction sur le prochain ID à venir.
  2. Chaque nouvelle ID créé est de la forme 5XXXXX ou 6XXXXX (d'après mes tests). Il est donc possible que les ID de la forme 4XXXXX, 3XXXXX, 2XXXXX est déjà été tous utilisé.
    1. Il est donc fort probable que l'algorithme de Tinyurl, répartisse les ID fraichement créé sur deux plages qui n'ont pas encore été complètement remplie (dans notre cas 5XXXXX et 6XXXXX). Nous pouvons émettre cette hypothèse vu que les plages [4XXXXX, 3XXXXX] et [2XXXXX, 1XXXXX] on déjà été rempli.
      1. Exemple, si l'on entre http://google.com l'ID de TinyUrl est http://tinyurl.com/1c2 : notre théorie est donc sans doute valide car cette adresse à été entrée dans les débuts de Tinyurl (par une personne qui souhaitait tester le service) et qu'au lancement l'algorithme devait travailler sur une plage [2XXXXX, 1XXXXX].
  3. L'algorithme semble donc bien plus complexe que celui élaboré plus haut.

 

Nous avons donc une base d'algorithme pour créer notre service, bien sur, il est extrêmement conseillé de l'améliorer mais il reste néanmoins fonctionnel et c'est ce que l'on souhaite d'un algorithme n'est-ce pas ?

6/30/2008

Équivalent Javascript pour les fonctions PHP ksort et krsort [MAJ]

Il y a quelques minutes, j'ai eu besoin de trier un tableau associatif javascript par ses index, du plus petit au plus grand. Mais javascript (via la méthode sort() de l'objet Array) ne permet que le trie des éléments d'un tableau, et non de ses index. Après une petite recherche, je me suis basé sur le code de Aaron Gustafson afin de créer la fonction ksort() et son opposé krsort().

[MAJ] : Le code de Aaron Gustafson ne prends pas en charge les tableaux de tableau ou d'objet, ni les tableaux de tableau de tableau. Ce qui est très nul dommage. J'ai donc modifié et optimisé tout ça :

/*
    array ksort  ( array $array)
    Trie le tableau array  suivant les clés, en maintenant la correspondance entre les clés et les valeurs.
    Cette fonction est pratique pour les tableaux associatifs.
*/
function ksort(w)
{
  var sArr = [];
  var tArr = [];
  var n = 0;
  for (i in w)
  {
    tArr[n++] = i;
  }
  //tri du plus petit au plus grand
  tArr = tArr.sort();
  n = tArr.length;
  for (var i=0; i<n; i++) {
    sArr[tArr[i]] = w[tArr[i]];
  }
  return sArr;
}
/*
    array krsort  ( array $array)
    krsort() trie le tableau array  en ordre inverse et suivant les clés, en maintenant la correspondance entre les clés et les valeurs.
    Cette fonction est pratique pour les tableaux associatifs.
*/
function krsort(w)
{
  var sArr = [];
  var tArr = [];
  var n = 0;
  for (i in w)
  {
    tArr[n++] = i;
  }
  //tri du plus grand au plus petit
  tArr = tArr.sort(function(a,b){return (b - a);});
  n = tArr.length;
  for (var i=0; i<n; i++)
  {
    sArr[tArr[i]] = w[tArr[i]];
  }
  return sArr;
}

J'en profite pour vous annoncer la naissance prochaine d'un projet sous Adobe Air. A ce propos je cherche des Alpha-testeurs (oui, à ce stade on peut parler d'Alpha plutôt que de bêta) donc n'hésitez pas à vous faire connaître en commentaire.

6/26/2008

La rétro-ingénierie (reverse-engineering) appliquée à un mini-projet

Avant de commencer cet article, je souhaite préciser plusieurs choses :

  1. Je suis autodidacte, je n'ai aucune formation scolaire sur le sujet, il est donc possible que je n'emploie pas les bons termes, ne sortez pas le fouet pour autant.
  2. Je montrerai dans ce poste qu'un bref aperçu de mes méthodes de R-E (Reverse-engineering), mon but n'est pas de former, mais simplement d'expliquer la démarche.
  3. J'utilise la rétro-ingénierie à des fins de formation personnel et en aucun cas pour de la contrefaçon ou autre forme de piraterie.


Base d'une réflexion de rétro-ingénierie

Pour commencer, nous allons résumer rapidement le projet : Nous devons créer un équivalent à TwitterCounter mais pour Plurk (que nous appellerons PlurkCounter).

La page d'un utilisateur sur TC (TwitterCounter) est de la forme :

TwitterCounter- How popular are you- (open beta)_1214486815920

Maintenant l'idée consiste à chercher l'ensemble des informations dont on va avoir besoin pour réaliser un service similaire. On a donc besoin :

  • De connaitre le nombre de followers actuellement.
    • Pour l'afficher dans le badge/logo.
    • Pour l'afficher dans le graphique dans la colonne de droite.
  • On a besoin de connaitre le nombre de followers au jour X (dans le passé).
    • Pour afficher l'évolution du nombre de followers dans le graphique.
      • On aura donc besoin de stocker un tableau permettant une relation entre les jours et le nombre de followers pour ces jours-là.

Et c'est déjà fini ! Il ne reste plus qu'à retranscrire cela par un algorithme puis par du code, en allant du plus simple au plus complexe. L'objectif et de voir ce que vous pouvez recréer, puis, une fois vos acquis évalués, essayez de voir comment faire pour chercher les informations qui vous manquent.

 

Quelques pistes d'algorithme :

  1. Cherchez comment retrouver le nombre de followers actuels d'un utilisateur (Plurk ou Twitter ou même autre).
  2. Créez un système de cache qui permettra de ne pas aller rechercher l'information si elle n'est pas périmée :
    1. Si (un fichier cache existe pour cet utilisateur et qu'il date de plus de 24h) OU Si(le fichier cache de cette utilisateur n'existe pas)
      1. Chercher le nombre de followers de cet utilisateur et créer le fichier cache.
    2. Sinon
      1. Ouvrir le fichier cache et récupérer/afficher le nombre de followers.
  3. Ensuite pour la journalisation, et permettre le suivi du nombre de followers en fonction du temps, ajoutez un test à votre algorithme :
    1. Si (le fichier cache pour cet utilisateur existe) ET (le fichier cache date de plus de 24h)
      1. On enregistre dans une base de données/fichier le nombre de followers pour la date du fichier cache.
  4. Il ne vous reste plus qu'à afficher les données sous la forme que vous souhaitez.

 

Autre exemple : Reproduire le graphique de TC

Intéressons nous maintenant à l'affichage des données sous la forme de graphique, comme le montre TC :

TwitterCounter- How popular are you- (open beta)_1214487161004

Émettons que vous réussissiez à créer d'une façon ou d'une autre une base de données (ou un tableau) qui contient le nombre de followers en fonction de la date.

La question qu'il reste à vous poser est comment reproduire ce type de graphique ?

  1. Vous avez forcément le nombre de followers d'aujourd'hui pour cet utilisateur, donc la colonne de droite sera toujours remplie.
  2. Ensuite recherchez si hier, pour cet utilisateur, vous aviez le nombre de ses followers :
    1. si oui : vous affichez l'information.
    2. si non : vous informer l'utilisateur que vous n'avez pas de données pour ce jour-là.
  3. Vous pouvez effectuer une boucle jusqu'à J-X (pour TC la boucle va jusqu'à 7 jours en arrière, pour PlurkCounter la boucle va jusqu'à 8 jours en arrière) de la même façon.

 

Voila j'espère que cette petite initiation vous à plu, n'hésitez pas à tester PlurkCounter si vous êtes un utilisateur de Plurk.

6/20/2008

Nouveauté PlurkCounter : suivi du nombre de followers à la FeedBurner

Voila, PlurkCounter ne pouvait devenir l'équivalent de TwitterCounter sans avoir le suivi du nombre de followers jours par jours et c'est maintenant chose faite !

Le service vient d'être accessible pour tout le monde depuis quelques heures. Les fichiers caches les plus anciens étant ré-actualisé les personnes qui ne pouvait suivre leurs followers hier devrait ne plus rencontrer aucun problème.

 image

NDLR : J'hésite à faire un petit article sur la rétro-ingénierie (Reverse Enginering) car inconsciemment j'utilise cette méthode. Je n'ai pourtant pas lu un seul article sur le sujet mais je pense que c'est le mot qui qualifie le mieux, au final, sur ce que je fais. A voir donc...

6/16/2008

Exécuter une tâche après l'affichage d'une page php

Il arrive parfois qu'un développeur PHP ait besoin d'effectuer plusieurs opérations qui ne nécessitent pas de modifier la page à envoyer au navigateur. Il est donc intéressant de pouvoir continuer à exécuter un script même si les en-têtes ainsi que le contenu de la page ont déjà été envoyé au navigateur. On parle alors de fonction d'extinction. Pour enregistrer une fonction d'extinction on utilise la fonction register_shutdown_function qui est de la forme :

void register_shutdown_function ( callback $function [, mixed $parameter [, mixed $... ]] )

Voici un exemple d'utilisation :

<?php
function apres_envoi($var1,$var2)
{
    //code à executer après l'envoi de la page
}


set_time_limit(0);
register_shutdown_function('apres_envoi','maVariable1',$variable2);

//code pour l'affichage de la page
?>

Et voila !

6/13/2008

Après TwitterCounter voici PlurkCounter, afficher le nombre de vos followers Plurk sur votre blog

Il y a quelques heures, j'ai vu sur le blog de GuiM, un nouveau service pour twitter appelé TwitterCounter. Quelques lignes de code plus tard, voici donc PlurkCounter, un service permettant d'afficher le nombre de ses followers Plurk sur son blog. Tujours sur le même principe, il suffit d'entrer son identifiant Plurk (par exemple GeekFG) et le service vous propose les widgets à intégrer à votre blog.

  image

Pour le moment un seul format de widget est disponible, mais n'hésitez pas à proposer vos idées dans les commentaires, de plus je prévois une version anglaise du service.

 

PS : Je souhaite remercier Philippe d'Accessoweb ainsi que tous ceux qui ont relayés et qui relaient les petits projets que je développe, cela me fait un grand et réel plaisir d'avoir des retours ! Si vous parler de mes projets sur votre blog ou votre site n'hésitez pas à poster un petit commentaire pour donner votre avis sur le service ou simplement un lien vers votre article afin que je puisse recueillir vos opinions. Encore merci.

6/12/2008

Afficher son Karma Plurk dans son blog via un widget/gadget

Comme prévu, je vous informe du lancement d'un petit service qui permet tout simplement d'afficher son Karma Plurk sur son blog/site.

Dans un premier temps, entrez votre identifiant Plurk. Votre identifiant Plurk est ce qui est contenu dans l'adresse http://www.plurk.com/user/XXXXX, puis cliquez sur le bouton de validation, ensuite vous aurez une page de la forme :

Capture d'écran du service permettant d'afficher son karma plurk sur son site

Pour le moment seul deux widgets/gadgets sont disponibles, mais je compte bien en ajouter dès que possible. Le service est donc disponible ici.

6/11/2008

Lancement du site projets.geekfg.net, J+1

Petit message pour vous informer dans l'annonce prochaine (sans doute une question d'heure) d'un nouveau service sur GeekFG's web services & applications ! En effet après l'assistant de création de Bookmarklet pour ajouter une signature HTML à vos emails Gmail, le prochain service s'adresse aux utilisateurs de Plurk.

L'api n'est pas encore sortit mais cela ne m'a pas empêcher de créer une petite (mais vraiment petite) application web pour webmaster et bloggeur possédant un compte Plurk. Affaire à suivre donc...

6/09/2008

Bookmarklet creator : Ajouter une signature html à vos emails Gmail [suite]

Dans le précédent article Comment ajouter une signature html à vos mails Gmail, je vous expliquait comment créer un bookmarklet afin d'afficher une signature html dans vos emails Gmail. Le problème est que la procédure peut-être un peu difficile pour un public non avertit.

C'est pour cela que j'ai la joie de vous annoncer le lancement d'un outils de création en ligne de bookmarklet (dans notre cas de signature html pour Gmail).

Pour accéder à l'outils c'est par ici : Comment ajouter une signature HTML sous Gmail.

6/06/2008

Amusons-nous avec Plurk [1/2] : Poster un message sur Plurk avec PHP/Curl

Nous allons voir de cet article comment envoyer un message sur Plurk grâce à Curl et PHP. Pour le moment Plurk ne propose pas d'API, ni de documentation, mais votre serviteur à regardé attentivement pendant plusieurs minutes le fonctionnement de la bête afin de pouvoir vous proposer ces quelques morceaux de code.

Etape 1 : Vous inscrire à Plurk (si ce n'est pas déjà fait)

Courrez vous inscrire à Plurk, vous pouvez utiliser ce lien, qui vous permettra une fois inscrit, de m'avoir directement en friends (la chance que vous avez).

Etape 2 : Récupérer votre identifiant Plurk

plurk_logoContrairement à ce que l'on pourrait penser votre identifiant n'est pas votre nom d'utilisateur. Il peut être sous deux formes :

  • AFVeMES9QZpm (exemple d'identifiant privé, contenu dans un cookie après la connexion à Plurk)
  • 33527 (mon identifiant public disponible dans le code de ma page Plurk)

Si vous souhaitez envoyer un message sur Plurk il vous faut les données de votre cookie Plurk. Pour le récupéré j'ai donc créé un petit bookmarklet (encore un bookmarklet ?).

  1. Déplacez ce lien : Plurk (drag & drop) dans votre barre de favoris.
  2. Connectez-vous à Plurk, puis cliquez sur le favoris pour afficher votre cookie Plurk (copiez le) et votre identifiant privé.
  3. Vos possédez maintenant les données qui vous permettrons d'ajouter un message.

Petite anecdote : à la création de cet article, seul l'identifiant privé était nécessaire pour l'ajout d'un message sous Plurk, mais à l'heure actuelle, les variables first_plurk et modified sont obligatoire pour l'ajout d'un post. Je prévient donc qu'il n'y à aucune garantie pour que mon code fonctionne dans les jours à venir ;).

Etape 3 : Poster un message sur Plurk via Php/Curl, le code

function post_to_plurk($content= 'http://geekfg.blogspot.com',$qualifier = ':',$lang = 'fr')
{
// Entrez ici votre cookie Plurk trouvé grâce au bookmarklet
$COOKIE_CURL = '000000000000000000000000000000=?user_id=000000000000&first_plurk=00000000000000000000&modified=00000000=';

//Vous n'êtes pas obliger de toucher au code ci-dessous
$header = array('Cookie: plurkcookie='.$COOKIE_CURL);
$ch = @curl_init();
@curl_setopt($ch, CURLOPT_URL, 'http://www.plurk.com/TimeLine/addPlurk');
@curl_setopt($ch, CURLOPT_HEADER, 0);
@curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
@curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
@curl_setopt($ch, CURLOPT_POST, 1);
@curl_setopt($ch, CURLOPT_POSTFIELDS, 'posted='.rawurlencode(date('Y-n-j').'T'.(date('G')-2).':'.date('i:s')).'&qualifier='.rawurlencode($qualifier).'&content='.rawurlencode(utf8_encode($content)).'&lang='.$lang.'&no_comments=0');
@curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
$data = @curl_exec($ch);
$res = @curl_getinfo($ch);
if($res['http_code'] == 500)
{
return 'Erreur lors de l\'envoi au serveur : les paramètres saisis sont sans doute mauvais';
}
else if($res['http_code'] == 200)
{
return 'Message posté ! Voici ce que retourne le serveur : '.$data;
}
else if($res['http_code'] == 400)
{
return 'Erreur du serveur : '.$data;
}
@curl_close($ch);
}

Modifiez simplement le contenu de la variable $COOKIE_CURL par les données que vous a donné le bookmarklet tout à l'heure, ces données sont normalement de la forme :

000000000000000000000000000000=?user_id=000000000000&first_plurk=00000000000000000000&modified=00000000=

Une fois modifié, vous pouvez utiliser la fonction comme ceci :

echo post_to_plurk('Hello World'); //Plurk affichera : [PSEUDO] Hello World

Ou encore comme ceci :

echo post_to_plurk('être riche','wishes','fr'); //Plurk affichera : [PSEUDO] souhaite être riche

Autre version du code

Cette autre version (que je viens de trouver ici), se connecte à plurk, récupère les données du cookie et envoi un message sur Plurk.

function post_to_plurk2($content= 'http://geekfg.blogspot.com',$qualifier = ':',$lang = 'fr')
{
//Entrez ici vos identifiants de connexion Plurk
$nomutilisateur = 'LOGIN';
$motdepasse = 'MOTDEPASSE';

//Vous n'êtes pas obliger de toucher au code ci-dessous
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_COOKIEJAR, 'plurkcookie.txt');
curl_setopt($curl, CURLOPT_COOKIEFILE, 'plurkcookie.txt');
curl_setopt($curl, CURLOPT_URL, 'http://www.plurk.com/Users/login');
curl_setopt($curl, CURLOPT_POSTFIELDS, 'nick_name='.$nomutilisateur.'&password='.$motdepasse);
curl_exec($curl);
curl_setopt($curl, CURLOPT_URL, 'http://www.plurk.com/TimeLine/addPlurk');
curl_setopt($curl, CURLOPT_POSTFIELDS, 'qualifier='.rawurlencode($qualifier).'&content=' .rawurlencode(utf8_encode($content)). '&lang='.$lang.'&no_comments=0');
return curl_exec($curl);
curl_close($curl);
}

Voila, c'est finit pour aujourd'hui, mais la suite arrive demain ! N'hésitez pas à vous inscrire au flux rss pour suivre plus facilement le blog.

6/05/2008

Comment ajouter une signature html à vos mails Gmail

Logo Gmail Ce tutorial est pour les utilisateurs intensifs de Gmail. Comme vous l'avez sans doute remarqué, il vous est possible, depuis Gmail, de spécifier une signature à inclure à tout vos emails (Options > Général > Signature) malheureusement Gmail refuse l'ajout de code html depuis cette méthode (même en créant soit même la requête de type POST que Gmail effectue lors de la sauvegarde de vos préférences). Voici donc comment créer un bookmarklet qui ajoutera directement dans votre message votre signature.

Avant de commencer sachez que des extensions Firefox (Better Gmail 2) et script Grease Monkey permettent déjà cela. Mais si vous êtes un utilisateur nomade utilisant plusieurs navigateurs sur différentes machines la solution du bookmarklet est beaucoup plus rapide à mettre en place et simple d'utilisation.

Nous utiliserons JQuery afin de pouvoir travailler très simplement avec Gmail. Le lanceur de notre bookmarklet est basé sur l'article de WebInventif. Une fois Jquery chargé, il ne reste plus qu'à placer notre code dans la fonction "code()" (voir le code final de l'article WebInventif).

Google utilise des iframes avec des id et des class changeantes à chaque rechargement de page pour éviter toute tentative de piratage automatisé (envoi d'email automatique par exemple). Nous ne pouvons pas directement accéder à un élément par son id ou sa class mais nous pouvons y accéder en fonction de ses éléments parents qui eux ne changeront pas ! De plus, après avoir parcouru le code html de la page d'édition d'email, on observe que le conteneur du texte de l'email est un élément body avec la class editable. Notre page Gmail contient 4 iframes la dernière appelée par un id canvas_frame (qui lui ne change pas) et qui contient l'iframe qui nous intéresse.

Pour accéder au contenu d'une iframe avec Jquery, nous devons utiliser le code suivant :

$('iframe').contents()

Ensuite pour recherche un élement à l'intérieur de cette iframe (par exemple une autre iframe) on ajoute la propriété "find" :

$('iframe').contents().find('iframe')

Ainsi pour accéder directement au contenu de notre email, il suffit de faire :

$('iframe#canvas_frame').contents().find('iframe').contents().find('body.editable')

Ou d'une manière plus générale

$('iframe').contents().find('iframe').contents().find('body')

Il ne nous reste plus qu'à ajouter notre signature après le dernier élément de body.

$('iframe').contents().find('iframe').contents().find('body').append('<a href="http://feeds.feedburner.com/%7Er/geekfg/%7E6/2"><img src="http://feeds.feedburner.com/geekfg.2.gif" alt="GeekFG Blog Rss Feed" style="border: 0pt none ;"></a>);



Le code final de notre bookmarklet est alors :


void ((function(){
if (!document.getElementById("Ijquery")) {
var noeud_js = document.createElement("script");
noeud_js.setAttribute("type", "text/javascript");
noeud_js.setAttribute("id", "Ijquery");
noeud_js.setAttribute("src", "http://code.jquery.com/jquery-latest.pack.js");
document.getElementsByTagName("head")[0].appendChild(noeud_js);
}
function jquery_loaded(){
var tmp = "false";
try {tmp = $("body").text();}catch (erreur) {tmp = "false";}
return tmp;}
function verif_loaded(){
var temp = jquery_loaded();
if (temp != "false") {
clearInterval(interval);
code();
}
}
var interval = window.setInterval(verif_loaded, 100);
function code()
{
$("iframe").contents().find("iframe").contents().find("body.editable").append('<a href="http://feeds.feedburner.com/%7Er/geekfg/%7E6/2"><img src="http://feeds.feedburner.com/geekfg.2.gif" alt="GeekFG Blog Rss Feed" style="border: 0pt none ;"></a>');
}
}
)())


Une fois que vous avez modifier votre signature dans le code ci-dessus, effectuez les étapes suivantes :

  1. Allez ici, copier/coller y votre code, cliquez sur Encode
  2. Copier le code généré
  3. Créez un marque-page dans votre navigateur, allez dessus, supprimez l'ancienne adresse
  4. Ajoutez javascript:, puis coller le code javascript qui vient d'être encodé
  5. Enregistrez votre marque-page
  6. Rendez-vous sur Gmail, créez un nouvelle email
  7. Cliquez sur votre marque-page
  8. Après quelques secondes votre signature doit s'ajouter

Voici le bookmarklet de l'exemple glissez-déposez-le (drag & drop) dans votre barre de lien puis allez sur Gmail pour tester.

6/04/2008

Comment modifier l'extension Firefox Delicious Bookmark pour ne pas partager ses favoris

firefox Ce billet s'adresse aux personnes naviguant sous Firefox, utilisant l'extension Delicious Bookmarks (dans l'exemple, la version 2.0.48) et ne souhaitant pas partager leurs favoris.

Même si à l'origine del.icio.us est orienté vers le partage de favoris, le service peut tout à fait être utilisé comme centre de sauvegarde de favoris/marque-pages entre plusieurs navigateurs internet et il se peut que vous ne souhaitiez pas partager vos favoris pour diverses raisons (sécurité, confidentialité...).

Pour ce genre d'utilisation, il fallait à chaque fois, lors de l'ajout d'un marque-page cliquer sur do not share. Maintenant nous allons modifier le script pour ne plus à avoir à cliquer sur do not share.

  1. Rendez vous dans le répertoire de votre profil Firefox qui contient les extensions. L'adresse sous Windows XP (voir pour les autres systèmes) est sous la forme : G:\Documents and Settings\[VOTRE_COMPTE_UTILISATEUR]\Application Data\Mozilla\Firefox\Profiles\[VOTRE_PROFIL].default\extensions\
  2. Ensuite rendez vous dans le dossier {2fa4ed95-0317-4c6a-a74c-5f3e3912c1f9} ou effectuez une recherche sur le fichier ssrDelicious.js.
  3. Commentez les lignes suivantes (la ligne 1002 et 1004) pour que tout les prochains marque-pages soient ajoutés en mode non partagé

    //if (shared == "false") {
    queryString += "&shared=no";
    // }

  4. Enregistrez le fichier puis relancez Firefox.
  5. Maintenant lorsque vous ajoutez un marque-page, que vous cliquiez sur do not share ou non, votre marque-page ne sera pas partagé.
6/03/2008

Il manque une fonctionnalité à l'API de Twitter

twitterL'API de Twitter s'est beaucoup épaissi depuis son commencement pour notre plus grand bonheur ! Mais il manque toujours une fonctionnalité. En effet nous devons passer par le site pour pouvoir voir si nous avons de nouvelles demandes de following (dans le cas de compte Twitter privé) pourquoi l'API ne propose pas une liste des requêtes de following ? Ainsi on pourrait permettre aux utilisateurs d'accepter (ou non) directement depuis leurs applications favorites (twhirl, spaz ...) les followers prétendants.

J'ai envoyé cette demande à l'équipe de Twitter.

6/01/2008

Comment transférer un domaine de OVH vers 1&1

logoVenez d'acquérir un nom de domaine tendance depuis Domainfinder ou simplement grâce à l'offre spéciale de OVH sur les noms de domaine en .eu et vous souhaitez pouvoir gérer vos domaines depuis l'interface de 1&1 ? Ce billet est pour vous.

  1. Connectez vous le compte 1&1 qui vous accueillera votre futur domaine.
  2. Cliquez sur Configuration des domaines.
  3. Menu Transferts -> Effectuer un transfert.
  4. Entrez votre domaine, par exemple "eeeeeeeeeeeeeeeee.eu" puis cliquez sur Suivant
  5. Deux possibilités :
    1. soit vous souhaitez utiliser les DNS 1&1 et laisser l'enregistrement du domaine chez OVH (gratuit, notre cas).
    2. soit vous souhaitez transférer le nom de domaine sur 1&1 (payant).
  6. Cliquez sur Utiliser les serveurs DNS 1&1 et conserver votre prestataire actuel puis Suivant.
  7. Deux possibilités :
    1. Utiliser le serveur email OVH, vos adresses emails utilisant votre nom de domaine passeront par OVH (notre cas).
    2. Utiliser les serveurs email 1&1, vos adresses emails utilisant votre nom de domaine passeront par 1&1.
  8. Cliquez sur Utiliser le(s) serveur(s) email détecté(s) puis Suivant.
  9. Un récapitulatif montrant vos paramètres apparaît, retenez les deux adresses des serveurs de noms (DNS) de 1&1 inscrit dans la zone : Les serveurs de noms suivants doivent être transmis à votre prestataire actuel.
  10. Ouvrez un nouvelle onglet/fenêtre, et allez sur le manager OVH, connectez-vous.
  11. Sélectionner votre nom de domaine dans la liste.
  12. Dans la zone Accès aux sections, cliquez sur Domaine & DNS.
  13. Dans la zone Nom de domaine, cliquez sur Serveurs DNS.
  14. Les DNS actuelles de votre nom de domaine sont depuis OVH, ils ont une adresse de la forme *****.ovh.net, nous allons donc les modifier, pour cela cliquez sur Modification.
  15. Entrez les serveur de noms présent dans votre récapitulatif 1&1. Dans notre exemple ns61.1and1.fr (type primaire) et ns62.1and1.fr (type secondaire) puis cliquez sur Valider.
  16. Revenez dans le récapitulatif 1&1 et cliquez sur Commander (Si vous effectuez simplement un transfère de DNS, que vous souhaitez simplement utiliser les DNS 1&1 aucun paiement ne vous sera demandé).
  17. Vous recevrez des emails de OVH ("changement de dns") (et de 1&1) pour vous informer du bon déroulement des opérations.

Pour toute question, laissez un commentaire, je vous répondrais dès que possible.

5/29/2008

Synchronisation entre deux bases de données (Access/Mysql)

La première phase de mon stage consiste à mettre en place un script, un programme, qui permettra de synchroniser une partie de la base de données CIEL (qui contient l'ensemble des articles, famille, fournisseur, ventes, etc...) avec la base de donnée du site (Mysql).

CIEL repose sur une base de données ACCESS, le script devra donc être capable d'effectuer des requêtes sur cette base de données. La synchronisation est unidirectionnel (Ciel -> Site) lorsqu'il s'agit des articles, et bidirectionnel lorsqu'il s'agit des stocks.


Voici donc la façon dont j'effectue la synchronisation (dans cet exemple pour les articles).

Le serveur web du magasin accueil un mini-site, qui effectue via des requêtes AJAX les différents traitements de synchronisation. Le dialogue entre les deux serveurs s'effectue exclusivement en JSON, plus léger que XML et très facilement lisible en cas de debuggage.

Les requêtes AJAX envoyées depuis le serveur web du magasin peuvent être dirigées :

  1. soit vers un script php interne au serveur qui va permettre de créer un interface entre les données de la base de donnée ACCESS et le reste de l'application
  2. soit vers un script php "proxy" qui va effectuer une requête POST sur le serveur web e-commerce et retournera le résultat de cette requête. La requête POST ne contient qu'un seul champs : "data". Ce champs "data" - qui sera envoyé au serveur e-commerce - contient l'intégralité des variables POST ($_POST) envoyées au script proxy. Ainsi, le mini-site envoie une requête AJAX de type POST sur le script "proxy", le script proxy transforme toutes ces variables en JSON (serialisation) et les inclus dans la variable "data" qu'il envoi par POST au serveur web e-commerce, le serveur web e-commerce va alors déserialiser la variable $_POST['data'] et effectuer les traitements en fonction des paramètres transmis.


Ps : J'utilise CURL pour l'envoi de requête POST sur le serveur ainsi que PDO pour la communication avec la base de donnée ACCESS.

5/26/2008

Problème requête SQL avec INNER JOIN multiple sur base de donnée Access

Je viens de commencer réellement mon stage et pour cela, il me faut extraire des données d'une base de données Access par une requête SQL depuis PHP en utilisant PDO. Pour cela j'ai eu besoin de faire plusieurs INNER JOIN  (j'ai simplifié à 2 pour l'exemple) et une fois le deuxième INNER JOIN ajouté l'erreur suivante s'est produite :

[Microsoft][ODBC Microsoft Access Driver] Syntax error (missing operator) in query expression

Voici la requête produisant l'erreur :

SELECT Articles.code, Articles.libellélong, Articles.libellécourt, ArticlesTarifs.TTC, ArticlesStocks.QtéStock
FROM `Articles`
INNER JOIN `ArticlesTarifs` ON (Articles.N°) = ArticlesTarifs.N°Article
INNER JOIN `ArticlesStocks` ON (Articles.N°) = ArticlesStocks.N°Article
WHERE Articles.bWeb = 1

 

En fait, il suffit de concaténer tout les INNER JOIN directement dans le FROM de la requête et le tour est joué :

SELECT Articles.code, Articles.libellélong, Articles.libellécourt, ArticlesTarifs.TTC, ArticlesStocks.QtéStock
FROM (
(`Articles` INNER JOIN `ArticlesTarifs` ON Articles.N° = ArticlesTarifs.N°Article)
INNER JOIN `ArticlesStocks` ON Articles.N° = ArticlesStocks.N°Article)
WHERE Articles.bWeb = 1

 

Ainsi on a une requête sql sur la forme :

SELECT *
FROM (table 1 INNER JOIN `table2` ON table1.id = table2.id) INNER JOIN `table3` ON table1.id = table3.id)

 

Je reparlerai sans doute de PDO qui est vraiment une classe formidable

5/25/2008

Mon feedback sur Firefox 3

Un rapide Feedback sur Firefox 3 RC1 :
  • Il arrive un moment dans la navigation où il m' est impossible d' accéder à une page web lorsque celle-ci est directement entrée via la barre d' adresse le seul moyen pour y accéder est par un lien hypertexte, je suis donc obliger de redémarrer le navigateur pour pouvoir utiliser à nouveau la barre d' adresse, ce bug existait déjà sous Firefox 2.
  • La recherche rapide depuis la barre d'adresse est extrêmement intéressante cependant il faudrait prévoir un bouton qui permettrait de supprimer une entrée à la volée. Si j' entre monsite, on me propose http://monsite.com et je voudrais http://www.monsite.com mais, cette proposition arrive toujours en deuxième. Il serait donc intéressant d' ajouter un bouton pour supprimer l' entrée "http://monsite.com".
  • De la même façon, la gestionnaire de mot de passe devrait autoriser un mot de passe à être utilisé sur : tout le domaine; un seul sous-domaine spécifique etc... Par exemple, un mot de passe enregistré sur http://www.monsite.com ne s' affichera pas sur http://monsite.com, or il s' agit du même site ! Un effort est donc à faire sur ce point qui est pour moi essentiel.
5/22/2008

Transformer une image en code html via php et gd

Ces 2 dernières minutes, ne sachant pas quoi faire et rempli d'une profonde tristesse, j'ai eu l'idée (et quelle idée, c'est ce genre d'idée qui vous fait perdre votre temps) de créer un script, qui, à partir d'une image (dans notre exemple une image png) va la transformer en code (x)html en utilisant des propriétés css. Le code du script est disponible ici.

Rien de bien compliqué :
  1. On récupère la taille de l'image
  2. On ouvre l'image
  3. On fait une boucle sur les Y et les X
    • A chaque pixel X:Y on récupère son index
    • On créé un div à la position X;Y et on lui applique un background-color en ayant convertit l'index en RGB
  4. Et voila :)
J'ai ajouté la variable "coef" qui permet de spécifier un coefficient multiplicateur (=zoom), un coef de 1 est la taille normal.

Je pense que des optimisations sont possibles (eh oui, même sur un petit morceaux de code comme celui la !) :
  • Il suffirait de stocker tous les index et leurs positions dans un tableau. Ensuite il faudrait regarder si il y a des mêmes index consécutifs pour ainsi créer un seul div - avec une taille plus grande - au lieu de plusieurs, on allège ainsi la taille du rendu html.
  • Ou encore, faire une liste des différentes couleurs, leurs créer une classe css, et appliquer cette class sur les div (à condition que le nom des classes ne dépassent pas 2-3 caractères et que l'image ne contienne pas beaucoup de couleur)

Ci-joint un exemple généré avec le script et l'image originale utilisée, la page pèse plus de 2.5Mo alors que l'image fait 20.8Ko... Je n'ai jamais dit que le script avait une réel utilité !
« »
 
 
Made with on a hot august night from an airplane the 19th of March 2017.