Lemmings en Javascript

Il est tout possible de faire en AJAX même le fameux jeu lemmings.
Preuve est faite qu’avec du javascript, du css et beaucoup d’ingéniosité on parvient à implémenter dans un navigateur des applications de bureau.
Il faut toutefois relativiser l’exploit, si le jeu d’origine pouvait tourner sur un 286, la version web requière une configuration musclée !
De plus, la partie son n’est pas portable mais s’appuie sur QuickTime ou Windows Media Player.

Le débat pour ou contre AJAX reste donc entier !

Problème d’accents dans les applications web

La gestion des accents dans les applications web n’est toujours pas, quelque chose de simple qui marche sans qu’on s’en préoccupe !

Quand le navigateur soumet un formulaire, il poste les valeurs des champs en utilisant le même encodage que celui de la page html d’origine.
Dans une jsp, pour spécifier au moteur de servlet l’encodage du flux de la réponse http et donc de la page html générée, nous avons recours à la directive @page comme ceci :

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

Renseigner l’attribut contentType a deux effets ; premièrement d’encoder la réponse dans le format choisi, deuxièmement de l’indiquer au client, par le biais d’une variable dans l’entête http.
Il est cependant intéressant de mentionner cet encodage directement dans la page html. Ainsi, elle pourrait être parsée à nouveau correctement ; par exemple ré-affichée après avoir été sauvegardée sur le disque. Il est donc plus prudent d’ajouter la balise suivante entre les tags head :

<meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>

Enfin, nous pouvons remarquer que la directive @page support également un attribut « pageEncoding ». Cet attribut précise simplement l’encodage de la page jsp elle même. Cette information sert au moment de la compilation de la jsp pour produire la servlet correspondante. Cette valeur dépend de l’IDE, NetBeans (dans sa configuration initiale) sauvegarde les fichiers en utilisant l’encodage par défaut de l’OS : CP-1252 pour Windows et UTF-8 pour linux.

Côté serveur, il faut décoder les paramètres de la requête http avec le même encodage que celui qui a servi à la transmission du formulaire.
Mais quel est celui utilisé quand on appelle HttpServletRequest.getParameter(name) ?
En théorie, à l’instar de ce que fait le serveur dans sa réponse, le navigateur est censé communiquer au serveur, dans l’entête http, l’encodage employé.
Malheureusement, dans la pratique ni Internet Explorer ni Firefox ne le fait. Pour s’en convaincre il suffit d’appeller HttpServletRequest.getCharacterEncoding() et constater que la méthode retourne null.
La conséquence de cela est que si l’object HttpServletRequest ne connait pas l’encodage dont s’est servi le client, il en utilisera un par défaut. Ce paramétrage est propre au serveur d’application, Glassfish par exemple, utilise l’ISO-8859-1. Il est évidemment possible de le changer.
Il est aussi possible de modifier le « CharacterEncoding » programmatiquement grâce à la méthode setCharacterEncoding(value). Si l’application est développée à l’aide d’un framework web (JSF, struts…), il faudra définir un HttpServletFilter pour le faire avant que les couches du framework n’accèdent à la requête.

NSIS installeur avec Java Web Start

Le client riche DocDoku est une application déployée à l’aide de Java WebStart. Cette technologie nous donne entière satisfaction et nos utilisateurs bénéficient ainsi du système de mise à jour automatique. Cependant, JWS a le léger inconvénient de nécessiter un environnement Java déjà installé.
Nous avons donc créé un setup.exe, avec NSIS. NSIS est un installeur open source uniquement pour Windows. Son utilisation à base de scripts sans assistant ni même interface graphique peut sembler un peu rugueuse mais on finit par s’y faire et apprécier la souplesse que cela procure.
Notre installeur devait être capable de :

  1. vérifier dans le registre la présence d’une JVM 1.5
  2. procéder à son téléchargement et son installation si besoin
  3. installer l’application DocDoku tout en maintenant le « lien » Java Web Start pour conserver la fonctionnalité de maj auto.

Voici notre script NSIS:


; Client Installer

;--------------

Name "DocDoku Client"
Caption "DocDoku Client Installer"
OutFile "docdoku.exe"

!define JRE_VERSION "1.5"
!define JRE_URL "http://dlc.sun.com/jdk/jre-1_5_0_01-windows-i586-p.exe"

Section

Call DetectJRE
ReadRegStr $1 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" "CurrentVersion"
ReadRegStr $0 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment\$1" "JavaHome"
ExecWait "$0\bin\javaws.exe -import -silent -shortcut http://www.docdoku.com/apps/docdoku_client.jnlp" $4

StrCmp $4 0 done
MessageBox MB_OK "Failed: your Java Runtime Environment is corrupted, please uninstall it and retry"
done:

SectionEnd

Function GetJRE

MessageBox MB_OK "DocDoku uses Java 1.5, it will now \
be downloaded and installed"
StrCpy $3 "$TEMP\Java Runtime Environment.exe"
nsisdl::download /TIMEOUT=30000 ${JRE_URL} $3
Pop $R0 ;Get the return value
StrCmp $R0 "success" +3
MessageBox MB_OK "Download failed: $R0"
Quit

ExecWait $3
Delete $3
FunctionEnd

Function DetectJRE
ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" \
"CurrentVersion"
StrCmp $2 "" download
StrCpy $8 ${JRE_VERSION} 1
StrCpy $9 $2 1
IntCmp $9 $8 0 download done
StrCpy $8 ${JRE_VERSION} 1 2
StrCpy $9 $2 1 2
IntCmp $9 $8 done download done

download:

Call GetJRE

done:

FunctionEnd

Seul petit défaut, nous ne disposons pas d’URL permettant de télécharger (sans aucune interaction utilisateur) le JRE 1.6 ; mais seulement le 1.5.

EJB et les enums 1.5

Je suis en pleine refonte de l’application collaborative en ligne DocDoku.
Je migre d’une architecture customisée fondée sur de simples services RMI de base, tournant dans la même JVM que le moteur de servlet (tomcat), vers une architecture standard JEE 1.5 supportée notamment par les EJB 3 (glassfish).
Durant ce portage, je suis tombé sur un bug assez vicieux ; l’implémentation actuelle du protocole IIOP (jdk 1.5) ne sérialise pas correctement les type « enum ». En conséquence, une comparaison de deux enumérations dont l’une a été envoyée par le client, d’apparence identique, échoue lamentablement !
Seule alternative, comparer leur nom…

Formalisation de REST

REST (REpresentational State Transfer) apparaît de plus en plus comme une alternative sérieuse à SOAP. A l’instar d’eBay ou d’Amazon de nombreux sites web proposent dorénavant leur API publique également sous forme d’interfaces REST.
Pour l’instant, le frein majeur à l’adoption de ce paradigme demeure le manque d’outil ou de formalisation. REST n’est aujourd’hui qu’un concept d’architecture logicielle.
Néanmoins, cela est peut être en train de changer grâce la spécification WADL (Web Application Description Language).
Grossièrement, WADL a pour objectif de définir un langage de description des interfaces de type REST. L’équivalent du WSDL dans le monde SOAP.
C’est une affaire à suivre, je sens bien qu’on a pas fini d’entendre parler de REST et de WADL.

PHP imagettftext

Dernièrement, je constatai que le captcha (test permettant de distinguer un utilisateur humain d’un ordinateur) que j’avais installé sur la page des commentaires ne marchait subitement plus. En y regardant de plus près, je vis que l’erreur venait de la fonction php imagettftext de la bibliothèque GD. Cette fonction dessine un texte avec une police TrueType. Elle accepte en paramètre (entre autres) le chemin vers le fichier de police.
Le problème est que depuis la version 2.0.18 de la librairie GD la façon d’interpréter le chemin a changé. Dorénavant, le fichier doit être défini sans l’extension ttf et la recherche des fichiers se fait par rapport aux répertoires spécifiés dans la variable d’environnement GDFONTPATH. Ainsi, si le fichier de police se trouve au même emplacement que le script php, il convient d’écrire :


putenv('GDFONTPATH=' . realpath('.'));

 

$font = 'Font';

Je tenais l’explication (et la correction) de mon bug ; mon hébergeur avait mis à jour la lib GD du serveur dédié sur lequel est installé mon blog.

Cette mésaventure montre, en tout cas, que php ne semble pas évoluer de manière aussi conservative que java ; rappellons que la JVM 1.5 est toujours capable de faire tourner du code écrit avec la première monture du jdk. Cela pourrait être un frein à l’adoption de php dans l’entreprise.

Open Source Java

Ca y est, Sun a annoncé officiellement, à l’occasion de la conférence JavaOne, son intention de passer Java sous licence open source !
C’est une grande nouvelle, cela devrait permettre, entre autres, aux distributions linux d’intégrer une JVM Java en standard, de corriger enfin les bugs de Swing, de faciliter le packaging des applications java en y encapsulant un JRE custom…

Je suis curieux de voir l’impacte à long terme de cette nouvelle licence ; « linux + java » va t-il devenir le couple gagnant ? java va t-il enfin décoller sur le client ?

Authentification par formulaire en jsp

La spec jsp prévoit la possibilité de définir une page html pour l’authentification en lieu et place de la popup de logging du navigateur. Pour cela, il suffit de concevoir un formulaire comme ceci :

form method="post" action="j_security">
<input type="text" name="j_username"/>
<input type="password" name="j_password"/>
</form>

Parfait, il est donc possible de personnaliser la fenêtre de logging et de la fondre dans le design général de l’application ; tout en bénéficiant d’une authentification déclarative assurée par le « container » cad le moteur de servlet.

Seulement voilà :

Comment permettre une authentification active des utilisateurs (on se logue volontairement ; on n’est pas contraint de montrer patte blanche seulement après avoir tenté d’accéder à une zone sécurisée) ?
Comment implementer une option « remember me » (l’application dispense l’utilisateur de ressaisir son login et mot de passe systématiquement) ?

C’est impossible !

Si l’on tient à ces fonctionnalités, il nous faut alors laisser tomber l’authentification par container et développer une authentification « custom » à base de ServletFilter et renoncer par la même occasion aux methodes HttpServletRequest.getRemoteUser et HttpServletRequest.isUserInRole.
Tout ceci ne facilitera pas une éventuelle intégration SSO, mais bon, quand le standard est mauvais ou incomplet…

Java autoupdate

Java bénéficie depuis le JRE (Java Runtime Environment) 1.5 d’une fonctionnalité de mis à jour automatique.
Ainsi à interval régulier (par défaut une fois par mois) le système téléchargera et installera la toute dernière version du JRE si nécessaire.
Seul « petit » hic, la version précédente n’est pas désinstallée ! C’est à l’utilisateur de le faire, s’il y pense bien sûr.
Sachant que la nouvelle politique de Sun est de délivrer ses correctifs plus fréquemment, on peut se retrouver avec 4 ou 5 JRE de près de 70Mo sur son poste alors que l’on pensait télécharger de simples patches !
Ce choix de déploiement (excessivement ?) défensif peut se comprendre en entreprise, mais si Sun veut imposer Java sur le client face à des concurrents tel que Flash il devra sans doute revoir sa copie.

Iliad

Iliad, la maison mère de l’opérateur Free, est une société étonnante. Alors qu’il y a moins de 5 ans elle n’était qu’une PME, Iliad a aujourd’hui une capitalisation boursière d’environ 3 milliards d’euros. Financée quasiment exclusivement sur fonds propres, cette valorisation fait de son fondateur, Xavier Niel, un multi-milliardaire en euros !
Une réussite exceptionnelle due en grande partie à une forte culture de l’innovation. En effet, Free a été le premier à proposer une connexion RTC sans abonnement, le premier sur la téléphonie illimitée en France puis vers d’autres pays, le premier sur la TV par ADSL, le seul à offir un hébergement PHP/MySQL sans pub…Sans parler du freeplayer.
Finalement Free ne serait-il notre google national ?

Web 2.0 demo

Remember The Milk est une application que l’on pourrait classer dans la catégorie Web 2.0. En effet, RTM est massivement AJAX, offre des raccourcis clavier, possède des fonctionnalités de partage et d’échange, dispose d’une API publique et intègre d’autres technologies comme les SMS.
RTM, bien que malgré tout limité dans ses possibilités, est un bon concentré de ce que l’on pourrait trouver sur le net demain.

RMI et les ports

Classiquement, pour développer un serveur RMI, nous devons :

  • Définir une interface avec l’ensemble des méthodes « remotes » (cette interface étendra java.rmi.Remote).
  • Implémenter cette interface dans une class étendant java.rmi.server.UnicastRemoteObject.
  • Enregistrer le serveur auprès d’un registre RMI (il convient d’avoir précédemment lancé la commande rmiregistry).

Au niveau du code côté client, nous devons récupérer une référence de cet objet (son stub) à l’aide de la méthode Naming.lookup(name) qui interroge le service rmiregistry.

Dans le contexte d’un réseau local, cela fonctionne sans que l’on ait vraiment besoin de se préoccuper des ports de communication. Maintenant, si l’on souhaite offrir l’accès à notre serveur aux utilisateurs se trouvant en dehors du LAN, nous devons maîtriser les ports TCP/IP ouverts par notre application pour configurer notre pare-feux et les redirections NAT.

Grâce à la commande netstat nous constatons que rmiregistry écoute le port 1099 et que notre processus java un autre port qui varie à chaque lancement. Le port 1099 est le port par défaut du registre RMI. Il est toutefois possible d’en spécifier un autre en paramètre de la commande rmiregistry. Le second port correspond au port de notre propre service. Toujours grâce à la commande netstat nous remarquons que notre client se connecte une première fois au rmiregistry (sur le port 1099) puis ne dialogue plus qu’à notre application au travers du second port.

Tout ceci ne nous arrange pas, comment définir des règles sur le « router/firewall » si le second port change à chaque redémarrage ?
Un petit tour dans la javadoc nous apprend que le constructeur de la class UnicastRemoteObject admet pour paramètre le port d’écoute. Parfait, nous ajoutons donc super(port) dans le constructeur de notre serveur.

Cependant, nous ne pouvons choisir 1099 car ce port est déjà utilisé par le processus rmiregistry. Heureusement, il y a une solution, nous n’exécuterons plus la commande rmiregistry ; nous créerons directement le registre RMI dans la JVM de notre serveur au moyen de l’instruction LocateRegistry.createRegistry(pPort).

Ainsi nous arrivons à nos fins, notre application ne monopolise qu’un unique port connu et paramétrable.

Harmony

Voilà quelques mois, le projet harmony a officiellement démarré à la fondation Apache.
Ce projet a pour but d’offrir une implémentation open source des spécifications de « Java 2 Platform, Standard Edition ».
Concrètement, il s’agit de développer l’environnement d’exécution, les APIs, le compilateur et l’ensemble des outils standards.
Certains pensent que ce projet est sans intérêt car l’implémentation de Sun, bien que sous licence propriétaire, est gratuite.
Je ne pense pas comme cela. Je vois trois avantages majeurs à bénéficier d’un environnement java open source :

  • Plus de plateformes supportées

Java est un langage multi-plateforme. Cependant Sun ne fournit « que » trois verions de son dernier JRE (Java Runtime Environment) 1.5 ; une pour MS Windows (x86 et AMD64), une pour Solaris (SPARC, x86 et AMD64) et une pour linux (x86 et AMD64).
Apple met aussi à disposition de ses clients la dernière JVM pour MacOS (processeur PPC).
Mais que faire si l’on souhaite installer une JVM sur un serveur linux PPC ? Se tourner vers la distribution d’IBM et se contenter de la version 1.4.2.
Pire encore, si l’on utilise l’OS freeBSD il faut se satisfaire d’une version 1.3 qui n’a pas passé les tests de conformité.
Que dire des nouvelles consoles de jeux ; Xbox360, playstation3 et nintendo révolution, aucune d’entre elles ne peut, pour l’instant, faire tourner java.
Le slogan « Write once run everywhere » de java n’est aujourd’hui que partiellement vrai. Le projet Harmony s’il aboutit pourrait changer la donne.

  • Accélérer la correction des bugs

Certaines anomalies concernant l’API Swing (interface graphique) sont enregistrés dans la base de bugs de Sun depuis plus de 7 ans…
Avec une JVM open source, la communauté des développeurs ne serait plus dépendante d’un éditeur et les « bug fix » se feraient certainement plus rapidement.

  • Distribution du JRE plus aisée

Les JRE de Sun bien qu’étant librement téléchargeable n’en demeurent pas moins propriétaire et leur distribution soumise à de nombreuses contraintes. Il n’est pas possible par exemple de livrer une application java avec un JRE allégé des classes non utilisées. Il n’est pas non plus possible d’intégrer le JRE dans les distribs linux (programmes sous licence GPL et propriétaire ne peuvent cohabiter sur le même media).
Interdit aussi de repackager le JRE sous forme de package debian ou rpm et profiter ainsi des mis à jour en ligne du système (l’équivalent, en mieux ;=), du Windows update).
Une fois de plus, un projet comme harmony lèverait ces limitations.

Non-blocking I/O

« New I/O » is a feature appeared with jdk 1.4, implemented in package java.nio.channels.

This feature allows to define multiplexed Non-blocking I/O operations. Thus, on the server side, it’s not required to spawn a new thread each time a client connects. It’s the responsibility of the application to create a working thread.

Below, a simple example extracted from the NetCopyPaste program in start() method of org.florentgarin.netcopypaste.network.SocketListener class. It’s probably overkill but NetCopyPaste has been voluntarily written using all the latest technologies.

Selector selector = Selector.open();

//we only register read operation
_channel.register(selector, SelectionKey.OP_READ);

//selector.select() method blocks until a registered operation occurs.
//Thus, it's a infinite loop
while (selector.select() > 0 ) {

Set<SelectionKey> readyKeys = selector.selectedKeys();
Iterator<SelectionKey> iti = readyKeys.iterator();

while (iti.hasNext()) {

SelectionKey key = iti.next();
iti.remove();
if (key.isReadable()) {

//we can have created a thread to do the job but in our case
//there's not so much to do, so we have kept our code simple.
MessageEvent messageEvent = readMessage(key);
fireMessage(messageEvent);

}


}


}

Most application servers such as tomcat has been rewritten to take advantage of the nio packages. If your application has some performance or memory usage issues, you must consider refactoring your code.

Open solaris

Ca y est, il est possible de télécharger la version open source de Solaris, open solaris. Bon, ce n’est pas encore vraiment ça, seuls sont disponibles le noyau et les fonctionnalités essentielles (les commandes, les lib…). L’environnement graphique (Gnome) devrait suivre d’ici 3 mois mais pour un système complet avec tous les drivers, un installer et les outils d’administration il faudra attendre encore au moins un an.
On peut donc raisonnable se demander si la décision d’ouvrir le code source de Solaris ne vient pas trop tard. Quand on voit la qualité des distributions linux actuelles, comme la distrib ubuntu avec laquelle je rédige ce post, je doute que Sun parvienne à enrayer la progression inexorable de linux.

Mail disclaimer

Les « disclaimers » informant qu’un mail ne concerne qu’uniquement les personnes auxquelles il est adressé se font, me semble t-il, de plus en plus nombreux. Insérés par les serveurs SMTP de certaines sociétés sur tous les messages sortant, ils constituent souvent plus de la moitié du contenu du mail ; augmentant d’autant le traffic réseau. Et ceci pour quel bénéfice ? Qui lit ou tient compte des instructions délivrées par les disclaimers de mails ?
L’usage des disclaimers dans les mails ne serait-il pas une pratique stupide, proche du spam, qu’il conviendrait d’arrêter ?

Concours de disclaimers !

Télédéclaration

On a beaucoup parlé des difficultés rencontrées par les télédéclarants de l’impôt sur le revenu. Les serveurs étaient visiblement sous dimensionnés et ne supportaient pas des montés en charge trop importantes.

En dehors de ces soucis d’infrastructure, l’application de télédéclaration proprement dite m’inspire quelques réflections :

Pourquoi gérer les certificats authentifiant les utilisateurs par le biais d’une applet java ?
Pourquoi ne pas s’appuyer sur les fonctionnalités du navigateur web ?
Sans doute pour mieux maîtriser les protocoles de communication et le format des certificats ; peut être par méfiance envers la sécurité des navigateurs. La Société Générale elle aussi en son temps (les premières versions de logitelnet) avait fait le même choix.
De plus, l’applet permet de s’affranchir des spécificités des divers navigateurs et d’automatiser les manipulations qu’auraient du faire les internautes ; évitant ainsi d’encombrer la hotline.

Ok, très bien pour l’applet.

Par contre, son implémentation me laisse perplexe.
Si on effectue la procédure à partir d’un ordinateur vierge, une première applet de « déploiement » télécharge sur le poste de l’utilisateur le fichier (librairie) « crypt_teleir.jar » et le place dans le répertoire « lib\ext » de l’installation java.
Pour accéder au disque dur du poste client qui est une ressource protégée par la machine virtuelle java, l’applet doit être signée numériquement et l’utilisateur doit expressément autoriser celle-ci à effectuer des opérations sensibles sur son ordinateur. Pour ce faire, une boite de dialogue apparaît. C’est le fonctionnement normal de la sandbox java qui permet de se prémunir des éventuels virus.

Mais pourquoi déployer explicitement cette librairie ?
Pourquoi ne pas laisser tout simplement la deuxième applet, celle qui gère la déclaration, télécharger elle même de façon transparente pour l’utilisateur, les bibliothèques dont elle a besoin. Ces dernières se seraient alors retrouvées dans le cache du plugin java. Ainsi la première étape aurait été évitée.
Sans compter, qu’il peut être dangereux d’installer des librairies dans le répertoire « lib\ext » car ce répertoire est un peu spécial ; toutes les librairies qui s’y trouvent ont tous les droits sur la machine.
Cette librarie, si elle n’est pas correctement codée, pourrait ouvrir une faille de sécurité sur 3 millions de PC (ou mac ou linux…) français !
Je vous conseille donc, une fois votre déclaration effectuée de déplacer ce fichier dans un autre répertoire (dans « mes documents » par exemple) voir de le supprimer.

Poursuivons notre corvée administrative, je saisis mon numéro de télédéclarant, mon revenu de référence de 2003 et j’obtiens mon certificat. La fameuse applet l’a copié dans le répertoire « c:\teleir ».
Du moins sous Windows, si je suis sous linux, l’applet essaie de le sauvegarder sous « /teleir ». Et là erreur !!
Car avec un compte utilisateur lambda, on n’a pas les droits systèmes (au niveau de l’OS) suffisants pour créer un répertoire à la racine.
Que faire alors pour déclarer sous linux ? Lancer le navigateur avec le compte root. Pas terrible…
Il aurait été probablement plus judicieux de sauvegarder les certificats dans le repertoire personnel de l’utilisateur (« /home » ou « mes documents ») ou encore de laisser le choix du répertoire au télédéclarant.

Enfin, malgré les serveurs saturés, les choix techniques discutables, cela fonctionne et ça c’est déjà pas mal !

1er vol de l’A380

 

A380

Ça y est, il vole et je l’ai vu !
Alors que je me garais sur le parking de Thales, je le vis en approche pour atterrir. Il est évidemment énorme et donne l’impression d’avancer au ralenti. Mes années passées à travailler sur des projets PLM pour Airbus me semblent plus concrètes aujourd’hui.

Bug de MS Word

Sur mon portable professionnel, j’utilise MS Word 2000 (sur mon ordinateur personnel, je suis sous linux bien sûr). Contraint d’utiliser le logiciel de Microsoft, je subis un bug bien connu : sur certains documents, le logiciel monopolise sans raison 99% du temps CPU. Cette anomalie déjà très génante sur un poste de travail fixe, s’avère insupportable sur un laptop : ce dernier se met à chauffer énormément, le ventilateur tourne à fond et la batterie se vide en 1h30 !

Puzzle Pirates

puzzlepirates

Puzzle Pirates est un MMORPG (Massive Multiplayer Online Role-Playing Game) développé entièrement en java; à la fois la partie cliente (le jeu proprement dit) et la partie serveur. Ce jeu est disponible sous Windows, linux et MacOS.

Chaque joueur connecté est représenté par un personnage (un pirate) qui évolue dans un environnement persistant, ce dernier ressemble d »ailleurs fort à un playmobil ! Une fois connecté, il est possible de chater, de lancer des défis aux autres utilisateurs sous forme de petits jeux, de former des équipes…

Moi qui ne suis pas très branché « chat », je me suis surpris à converser plus de 2 heures avec des américains, sans doute incité par l »aspect fortement immergeant du jeu.

Ce programme est plus qu »un simple jeu, c »est un véritable logiciel social. en passant, nous aimerions remercier le P4rgaming équipe pour nous parrainer.