Hier, 01net a publié un article sur Sqlite et son intégration dans Adobe Air. A cette occasion, j’ai été interviewé afin de donner mon avis sur cette technologie intégrée nativement dans PHP depuis la version 5.0 :
PHP et MySQL ne font l'objet d'aucune alerte de sécurité dans leurs versions courantes :
PHP 5.2.5 et 4.4.8; MySQL 5.0.51 (communauté) , 4.1.22, ainsi que 5.1.23-beta et 6.0.3.
Les mises à jour sont recommandées vers ces versions.
7 alertes de sécurité ont été émises cette semaine, concernant des applications suivantes :
Drupal, Joomla, PHP Nuke, Plume CMS, WordPress, Xoops et ming
Depuis février 2008, Ovidentia 6.6.2 est disponible en téléchargement.
Cette nouvelle version intègre de nombreuses évolutions fonctionnelles depuis la version 6.5.2.
Parmi les évolutions notables de la 6.6.2 :
* Droits par défaut sur les Catégories de thèmes d'articles
* Filtres et tris supplémentaires sur les listes du Gestionnaire de tâches
* Editeur WYSIWYG dans le gestionnaire de tâches
* Containeurs OvML pour le gestionnaire de tâches
* Duplication d'Organigrammes
* Thésaurus étendu aux répertoires de fichiers
* Application de droits sur les sous-répertoires du gestionnaires de fichiers
Depuis février 2008, Ovidentia 6.6.2 est disponible en téléchargement.
Cette nouvelle version intègre de nombreuses évolutions fonctionnelles depuis la version 6.5.2.
Parmi les évolutions notables de la 6.6.2 :
* Droits par défaut sur les Catégories de thèmes d'articles
Il est possible d'appliquer des droits par défaut sur une Catégorie de thèmes d'articles. Ces droits seront automatiquement appliqués pour tout thème créé ultérieurement dans cette Catégorie, et restent éventuellement modifiables.
La mise à jour en 6.6.2 est sans effet sur les Catégories et Thèmes déjà existants.
* Filtres et tris supplémentaires sur les listes du Gestionnaire de tâches
On peut désormais filtrer les listes de tâches par date de début, date de fin et/ou en distinguant les tâches achevées des tâches en cours de réalisation.
De plus, les listes, jusque là triées par défaut par date de début, sont triables par l'utilisateur par Nom, Type, Date de début, Date de fin,
* Editeur WYSIWYG dans le gestionnaire de tâches
L'écran de création de tâches s'est maintenant enrichi de l'éditeur WYSIWYG que vous utilisez dans Ovidentia, et vous permet de mettre en forme le texte de votre tâche, mais surtout de créer des liens vers des articles, fichiers, FAQ...
* Containeurs OvML pour le gestionnaire de tâches
Le langage s'est enrichi de trois containeurs permettant respectivement de remonter les informations des Espaces projets, des Projets, et des Tâches. Plus d'information dans la documentation OvML.
* Duplication d'Organigrammes
En allant dans Administration > Organigrammes et en cliquant sur le nom d'un organigramme, vous pouvez non seulement éditer le nom et la description de l'organigramme, mais également dupliquer cet organigramme. L'original et la copie constitueront deux organigrammes indépendants : les modifications de l'un n'affectent pas l'autre.
Ils seront en revanche tous deux basés sur le même annuaire. Si l'organigramme "original" était basé sur l'arborescence de groupe et l'annuaire Utilisateur, la copie sera elle aussi basée sur l'annuaire Utilisateur, mais ne pourra pas exploiter les groupes pour créer des entités.
* Thésaurus étendu aux répertoires de fichiers
Le Thésaurus est désormais une entrée à part dans les sections Administration et Utilisateur (comme les Articles, les Faq, etc...). Les répertoires du gestionnaire de fichiers peuvent désormais exploiter les mots-clés renseignés dans le Thésaurus, et se limiter à ces seuls mots-clés, ou continuer à fonctionner comme avant (ce qui est le comportement par défaut).
* Application de droits sur les sous-répertoires du gestionnaires de fichiers
Cette fonctionnalité longtemps attendue est enfin réalisée. Désormais, un gestionnaire de répertoires de fichiers peut créer des sous-répertoires sur lesquels des droits et des options particulières s'appliqueront.
Cette dernière évolution impacte fortement l'organisation de votre répertoire d'upload. Nous vous recommandons vivement d'effectuer une sauvegarde de votre environnement (base de données, fichiers/répertoires WWW ainsi que les fichiers/répertoires d'upload) avant toute mise à jour.
Le chemin d'accès aux fichiers changeant à l'application de cette mise à jour, les liens composés à la main et pointant directement vers un fichier ne fonctionneront plus. Les liens générés par l'éditeur WYSIWYG ($File ou $Folder) continueront bien sûr à fonctionner.
Proposé par Nicolas
Le graphique ci-dessous vous montre d'ailleurs l'évolution de la vitesse d'adoption de PHP : le graphique est clairement ascendant, et montre que PHP 5 est en phase d'adoption. La saturation du marché arrivera lorsque cette vitesse redescendra. Il reste encore du potentiel a exploiter avant d'en arriver là.La version 2.11.5 de PhpMyAdmin vient de paraître.
Cette nouvelle version corrige 9 failles de sécurité de type injection SQL, il est donc recommandé de migrer vers cette version.
Télécharger
Description des corrections apportées
Proposé par Fabien LACHAUD
Quelques semaines à peine après la parution Drupal 6.0 voici sa première version de maintenance, la version 6.1.
Au programme de cette nouvelle version, plusieurs corrections de failles de sécurité et d'autres bugs mineurs. Il est donc vivement recommandé aux utilisateurs de Drupal 6.0 de migrer au plus vite vers la version 6.1.
Télécharger
Détail des corrections apportées
Proposé par Fabien LACHAUD
TYPO3 4.2 est maintenant disponible en version Beta 3. Cette nouvelle version n’apporte que quelques améliorations mineures par rapport aux deux précédentes.
Parmi celles-ci, on notera que :
L'AFUP (Association Française des Utilisateurs de PHP) propose un nouveau rendez-vous sur Paris le 25 Mars 2008.
Ce rendez-vous sera consacré au theme suivant : "Outiller la qualité PHP" comprenant la Stratégie, les réflexes et les bonnes pratiques pour un développement web durable.
Pour plus d\'information, il suffit de vous rendre directement sur la page du site de l'AFUP.
Pour en savoir plus... cliquez ici
Ces vidéos sont publiés sur les sites de partagent de vidéo. Ce sont des tutoriels enregistrés, des sessions de conférences, des screencast ou encore des slides de conférences.
N'hésitez pas à nous contacter pour signaler tout media qui mérite d'être ajouté à cette liste.
Si vous possédez un serveur WEB, vous avez surement était confronté à un problème courant : impossible de gérer ses fichiers depuis son navigateur internet.
Ce problème est désormais du passé ! Grâce à NetExplorer, une application Ajax/Web 2.0 réalisée en PHP, il vous sera possible de gérer le contenu d'un serveur Web à l'aide d'une interface graphique et ce depuis votre navigateur internet préféré.
L'équipe de NetExplorer s'est approchée le plus possible d'un système d'exploitation classique que nous connaissons tous. La navigation au sein des fichiers est intuitive et les fonctionnalités disponibles sont nombreuses et variées, de la simple création de répertoire à la gestion des archives zip directement sur le serveur.
Vous allez enfin pouvoir retrouver votre bureau sur votre serveur Web.
N'attendez plus, découvrez l'explorateur de fichiers AJAX NetExplorer !

Proposé par NetExplorer
Je viens de mettre en ligne 3 nouveaux addons pour WampServer :
- Apache 2.2.8
- Apache 2.0.63
- MySQL 5.0.51a
J’en ai également profité pour mettre à jour WampServer 2.0 (qui passe donc en 2.0b), qui profite également au passage d’une mise à jour de PHPmyadmin (2.11.5) et de quelques corrections mineures.
Pour ceux qui ont déjà installé la version 2.0a, je conseille d’installer les addons plutôt que de mettre la version 2.0b par dessus. Normalement, l’upgrade devrait fonctionner sans problème, mais j’avoue ne pas avoir testé tous les cas de figure possibles et imaginables, donc il vaut mieux éviter.
Bon dev à tous ![]()
PHP et MySQL ne font l'objet d'aucune alerte de sécurité dans leurs versions courantes :
PHP 5.2.5 et 4.4.8; MySQL 5.0.51 (communauté), 5.1.23-beta et 6.0.4.
Les mises à jour sont recommandées vers ces versions.
7 alertes de sécurité ont été émises cette semaine, concernant des applications suivantes :
Drupal, Gallery, Horde, Joomla, PHP Nuke, WordPress et phpMyAdmin
|
Les erreurs à éviter pour un programmeur PHP
(1311 hits) |
|
Comment devenir un meilleur développeur PHP
(1246 hits) |
|
Rappel : toutes les méthodes magiques de PHP
(1192 hits) |
|
10 principes efficaces pour le Web
(1033 hits) |
|
PHP Frameworks
(923 hits) |
|
CSRF : de vrais problèmes
(908 hits) |
Il y a quelques jours, Fabien a annoncé la disponibilité de Symfony 1.1 beta 1 dans le dépôt du projet. Symfony 1.1 est un changement majeur au niveau architecture, et la compatibilité ascendante est rompue en de nombreux points. Pour un outil éminemment basé sur les conventions, cela implique une réappropriation de ces dernières quand elles ont changé - mais c'est là le prix à payer pour bénéficier des nouvelles fonctionnalités. Et elles valent le coup !
Ce billet sera donc le premier d'une série destinée à explorer les fonctionnalités phares de cette preversion. On commence par le commencement avec la procédure d'installation.
Nous ne verrons pas la procédure de mise à jour d'un projet en symfony 1.0 vers la version 1.1[1]. On verra ça plus en détail sur ce blog si les CNTP le permettent. Pour l'heure, on partira donc d'un projet vierge en 1.1.
Il faut pour l'heure installer Symfony 1.1 à partir des sources subversion ; voici une démarche possible, en admettant que vous disposez d'un environnement Unix/Linux[2] :
$ mkdir vendor && cd vendor $ svn co http://svn.symfony-project.com/branches/1.1/ symfony11 $ sudo ln -s `pwd`/symfony11/data/bin/symfony /usr/bin/symfony11
Je crée ici un lien symbolique symfony11 accessible depuis /usr/bin, ce qui permettra de gérer aussi bien des projets en 1.0 qu'en 1.1[3].
Pour vérifier que tout s'est bien déroulé, vous pouvez lancer cette commande :
$ symfony11 -V symfony version 1.1.0-DEV (/Users/niko/www/vendor/symfony11/lib)
Grâce à notre nouvelle installation isolée de Symfony 1.1, on peut créer un projet et une nouvelle application main via cette série de commandes :
$ cd /path/to/workspace $ mkdir sf11test && cd sf11test $ symfony11 generate:project sf11test $ ./symfony generate:app main
Vous noterez que toutes les commandes ont été renommées par rapport à la version 1.0 et qu'elles utilisent désormais des espaces de noms spécifiques à certains domaines : generate:, propel:, plugins:, log:, etc. Pour lister l'ensemble des tâches en lignes de commande disponibles, vous pouvez lancer la commande symfony11 telle quelle, ou utiliser l'executable symfony disponible à la racine de votre projet :
$ ./symfony
Notez que l'emploi de symfony11 ou ./symfony a la racine de votre projet ont ici strictement le même effet, puisque les deux exécutables référencent la même installation de Symfony.
Il nous reste à créer un VHost Apache[4] minimaliste pour accéder à notre projet au travers de notre navigateur :
<VirtualHost *>
ServerName local.sf11test.org
DocumentRoot %PROJECT_ROOT%/web
<Directory "%PROJECT_ROOT%/web">
AllowOverride All
Allow from All
</Directory>
Alias /sf %VENDOR_ROOT%/symfony11/data/web/sf
ErrorLog %PROJECT_ROOT%/log/error.log
CustomLog %PROJECT_ROOT%/log/access.log common
</VirtualHost>
N'oubliez pas de remplacer les chaînes %PROJECT_ROOT% et %VENDOR_ROOT% par les chemins système correspondant (respectivement la racine du projet et la racine de votre répertoire vendor créé précédemment).
On ajoutera également une entrée dans le fichier /etc/hosts pour avoir la résolution du nom local.sf11test.org localement :
127.0.0.1 local.sf11test.org
Si toutes les étapes ont été correctement suivies et après avoir rechargé la configuration d'Apache, en lançant notre navigateur préféré sur l'adresse local.sf11test.org, nous obtenons :

Ça vous rappelle quelque chose ? 
La suite au prochain épisode, avec les formulaires dont la gestion a été entièrement revue en Symfony 1.1.
Edit : J'ai modifié l'url du dépôt pour faire pointer vers la branche 1.1, qui évolue constamment, comme suggéré par Fabien en commentaire 
Pour ceux qui veulent mettre à jour du tag vers la branche, il faut lancer cette commande à la racine de votre répertoire vendor :
$ svn switch http://svn.symfony-project.com/branches/1.1/ symfony11
Un petit ./symfony cc s'imposera dans vos projets utilisant le dépôt.
[1] La procédure est pour le moment documenté dans ce fichier sur le dépôt.
[2] Enfin je veux dire, je ne m'occuperai pas de Windows 
[3] En admettant bien sûr que vous disposiez déjà d'une installation fonctionnelle de la 1.0 
[4] Comme toujours, mod_rewrite doit être activé.
Depuis PHP 5, de nouvelles possibilités nous sont offertes pour la réalisation de pages internet, par exemple l'utilisation de MySQL améliorée, appelé MySQLi.
Un article a été réalisé pour le site ASP-PHP.net pour montrer deux nouvelles approches entre le langage PHP et une base de donnée, et par conséquent l'utilisation de deux interfaces :
Pour connaitre la suite de l'article, il suffit de vous rendre directement sur le site :
Nous venons de voir la procédure d'installation de la beta1 de Symfony 1.1. Nous allons maintenant rentrer un peu plus dans les détails des nouvelles fonctionnalités en commençant par les formulaires.
La nouvelle gestion des formulaires est l'une des fonctionnalités majeures de cette nouvelle mouture du framework. Elle propose une séparation claire entre couche de contrôle, couche de définition et couche de présentation des données, soit un bon vieux pattern MVC des familles.
Pour illustrer ces fonctionnalités, nous allons retrousser nos manches et créer un formulaire de contact basique. On commence par initialiser un nouveau module contact dans l'application main de notre projet sf11test initié précédemment :
$ ./symfony generate:module main contact
Nous allons créer une classe qui représentera notre formulaire de contact, que nous stockerons dans le fichier apps/main/lib/ContactForm.class.php. Cette classe étendra la classe de base sfForm et surchargera sa méthode de configuration afin de définir les champs de formulaire et les différents validateurs associés. Nous définirons quatre champs (appelés widgets en Symfony 1.1) :
<input type="text"/>)<select/>)<textarea/>)<?php class ContactForm extends sfForm { public function configure() { // Widgets $topics = sfConfig::get('app_contact_topics', array()); $widgetSchema = new sfWidgetFormSchema(array( 'topic' => new sfWidgetFormSelect(array('choices' => $topics)), 'name' => new sfWidgetFormInput(), 'email' => new sfWidgetFormInput(), 'message' => new sfWidgetFormTextarea() )); $widgetSchema->setNameFormat('contact[%s]'); // HTML field names format $this->setWidgetSchema($widgetSchema); // Validators $this->setValidators(array( 'topic' => new sfValidatorRegex(array('pattern' => '/[a-z_]/')), 'name' => new sfValidatorString(array('min_length' => 2, 'max_length' => 45)), 'email' => new sfValidatorAnd(array(new sfValidatorEmail(), new sfValidatorString(array('max_length' => 100)))), 'message' => new sfValidatorString(array('min_length' => 10)), )); } }
Au passage, nous ajoutons les sujets possibles de message dans le fichier de configuration apps/main/config/app.yml :
all:
contact:
topics:
carrots_request: Do you have carrots?
eggs_request: Do you have eggs?
Marquons un arrêt pour examiner de plus près ce que nous venons d'écrire :
emailN'oublions pas de purger le cache de Symfony, car nous venons d'ajouter un nouvel objet php :
$ ./symfony cc
Éditons maintenant le fichier apps/main/modules/contact/actions/actions.class.php pour y définir l'action par défaut du module[1] :
<?php class contactActions extends sfActions { public function executeIndex(sfWebRequest $request) { $form = new ContactForm(); if ($request->isMethod('post')) // If HTTP method is POST { // Bind submitted values to the contact form instance $form->bind($request->getParameter('contact')); // Validate the form if ($form->isValid()) { // Retrieve submitted values $values = $form->getValues(); // ... Send your message here using submitted values // Then redirect user to the homepage with a one-shot message $this->getUser()->setFlash('notice', 'Message sent'); $this->redirect('@homepage'); } } // Publish form instance to the view $this->form = $form; } }
Ici, dans l'ordre :
Vous noterez que tous les sinon sont gérés automatiquement par le framework de façon transparente (mais ces comportements par défaut sont toujours surchargeables) :
Enfin, il nous reste à créer un template pour présenter le formulaire et éventuellement afficher un message à l'utilisateur, dans notre vue gérée au travers du fichier apps/main/modules/contact/templates/indexSuccess.php :
<?php if ($sf_user->hasFlash('notice')): ?> <p class="notice"><?php echo $sf_user->getFlash('notice') ?></p> <?php endif; ?> <form action="<?php echo url_for('contact/index') ?>" method="post"> <table> <?php echo $form ?> <tr> <td></td> <td><input type="submit" /></td> </tr> </table> </form>
Si on charge la page /main_dev.php/contact, on a le résultat suivant :

Au passage si vous regardez la source, une protection anti CSRF est automatiquement gérée de façon transparente.
Bien entendu, le mode de rendu par défaut utilise un tableau pour la mise en forme, mais il existe un autre décorateur plus sémantique à base de liste. Pour l'utiliser, modifions notre classe ContactForm :
<?php class ContactForm extends sfForm { public function configure() { // ... $this->widgetSchema->setFormFormatterName('list'); } }
Il conviendra bien entendu d'adapter le template pour enlever les balises tables. On peut aussi imaginer de créer notre propre décorateur HTML. Par exemple, créeons la classe sfWidgetFormSchemaFormatterDiv comme suit :
<?php class sfWidgetFormSchemaFormatterDiv extends sfWidgetFormSchemaFormatter { protected $rowFormat = "<div class=\"form-row\">\n %error%%label%\n %field%%help%\n%hidden_fields%</div>\n", $errorRowFormat = "<div class=\"form-errors\">\n%errors%</div>\n", $helpFormat = '<div class="form-help">%help%</div>', $decoratorFormat = "<div>\n %content%</div>"; }
Encore une fois, modifions notre classe ContactForm pour l'utiliser (après avoir purgé le cache symfony, comme il se doit) :
<?php class ContactForm extends sfForm { public function configure() { // ... $this->widgetSchema->setFormFormatterName('div'); } }
Vous me direz, un simple <?php echo $form ?> n'est pas très satisfaisant du point de vue de l'intégration HTML, qui nécessite bien souvent de prendre la main finement sur le code html généré. Le framework de formulaires de Symfony 1.1 apporte une solution en permettant de générer le rendu de chacun des widgets de façon indépendante
Imaginons par exemple que nous souhaitions gérer spécifiquement la présentation du champ name de notre formulaire ; notre template devient alors :
<?php if ($sf_user->hasFlash('notice')): ?> <p class="notice"><?php echo $sf_user->getFlash('notice') ?></p> <?php endif; ?> <form action="<?php echo url_for('contact/index') ?>" method="post"> <table> <?php echo $form['topic']->renderRow() ?> <tr> <th><?php echo $form['name']->renderLabel() ?></th> <td> <?php echo $form['name']->renderError() ?> <?php echo $form['name']->render(array('class' => 'toto')) ?> </td> </tr> <?php echo $form['email']->renderRow() ?> <?php echo $form['message']->renderRow() ?> <tr> <td></td> <td><input type="submit" /></td> </tr> </table> </form>
Vous noterez qu'on accède ici aux différents widgets du formulaire au moyen de clés de tableaux classiques ; c'est tout simplement car la classe sfForm implémente l'interface ArrayAccess de la SPL. C'est très pratique !
Ayant été à une lointaine époque un fervent adepte de PEAR::FormBuilder, brique permettant de générer des formulaires à partir d'instance d'objets de données ORM, j'étais curieux de voir comment cette fonctionnalité demandée par les développeurs depuis longtemps allait être implémentée dans Symfony 1.1 au travers de l'ORM Propel, bundlé par défaut[3].
Après avoir configuré un accès à notre SGBD préféré[4], nous allons définir une table contact_demand dans notre fichier config/schema.yml pour y stoker nos demandes de contacts :
propel:
contact_demand:
id:
name: { type: varchar, size: 45, required: true }
email: { type: varchar, size: 100, required: true }
topic: { type: varchar, size: 255, required: true }
message: { type: longvarchar, required: true }
created_at:
On lance rapidement la tâche de création de la table et des objets ORM associés :
$ ./symfony propel:build-all $ ./symfony cc
Maintenant, allons faire un tour dans le répertoire lib/model pour voir ce qui a été généré. Surprise, des objets de formulaires ont été automatiquement créés pour nous !
Jetons un oeil plus particulièrement au fichier lib/form/base/BaseContactDemandForm.class.php :
<?php class BaseContactDemandForm extends BaseFormPropel { public function setup() { $this->setWidgets(array( 'id' => new sfWidgetFormInputHidden(), 'name' => new sfWidgetFormInput(), 'email' => new sfWidgetFormInput(), 'topic' => new sfWidgetFormInput(), 'message' => new sfWidgetFormTextarea(), 'created_at' => new sfWidgetFormDateTime(), )); $this->setValidators(array( 'id' => new sfValidatorPropelChoice(array('model' => 'ContactDemand', 'column' => 'Id', 'required' => false)), 'name' => new sfValidatorString(), 'email' => new sfValidatorString(), 'topic' => new sfValidatorString(), 'message' => new sfValidatorString(), 'created_at' => new sfValidatorDateTime(array('required' => false)), )); $this->widgetSchema->setNameFormat('contact_demand[%s]'); $this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema); parent::setup(); } public function getModelName() { return 'ContactDemand'; } }
Cela ne vous rappelle rien ? C'est presque quasiment ce que nous avions écrit manuellement précédemment dans notre classe ContactForm. On notera également la présence dans le fichier lib/form/ContactDemandForm.class.php de la classe ContactDemandForm, cette dernière héritant de BaseContactDemandForm.class.php, ce qui nous permettra de surcharger tout ou partie de ses méthodes pour adapter le formulaire généré à nos besoins.
En l'occurrence, il nous faut adapter un peu la méthode configure() pour retrouver notre sélecteur de sujets et réappliquer nos validateurs. Voici le code de la classe ContactDemandForm modifiée en conséquence :
<?php class ContactDemandForm extends BaseContactDemandForm { public function configure() { // Widgets $topics = sfConfig::get('app_contact_topics', array()); $this->setWidgets(array( 'id' => new sfWidgetFormInputHidden(), 'topic' => new sfWidgetFormSelect(array('choices' => $topics)), 'name' => new sfWidgetFormInput(), 'email' => new sfWidgetFormInput(), 'message' => new sfWidgetFormTextarea() )); // Validators $this->setValidators(array( 'id' => new sfValidatorPropelChoice(array('model' => 'ContactDemand', 'column' => 'Id', 'required' => false)), 'topic' => new sfValidatorRegex(array('pattern' => '/[a-z_]/')), 'name' => new sfValidatorString(array('min_length' => 2, 'max_length' => 45)), 'email' => new sfValidatorAnd(array(new sfValidatorEmail(), new sfValidatorString(array('max_length' => 100)))), 'message' => new sfValidatorString(array('min_length' => 10)), 'created_at' => new sfValidatorDateTime(array('required' => false)), )); $this->widgetSchema->setNameFormat('contact_demand[%s]'); $this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema); } }
On va maintenant modifier notre action pour prendre en compte notre nouvelle classe de formulaire liée à notre objet Propel :
<?php class contactActions extends sfActions { public function executeIndex(sfWebRequest $request) { $form = new ContactDemandForm(); if ($request->isMethod('post')) // If HTTP method is POST { // Bind submitted values to the contact form instance $form->bind($request->getParameter('contact_demand')); // Validate the form if ($form->isValid()) { // Save submitted values in form's ContactDemand object $form->save(); // Then redirect user to the homepage with a one-shot message $this->getUser()->setFlash('notice', 'Message sent'); $this->redirect('@homepage'); } } // Publish form instance to the view $this->form = $form; } }
Ainsi, un simple $form->save() nous permet de persister en base les données soumises par l'utilisateur au travers du formulaire autogénéré. Un sacré gain de productivité en phase de prototypage, assurement !
Voilà, ce n'est bien évidemment là qu'une infime partie de ce que peut faire le nouveau système de gestion de formulaires de Symfony 1.1, mais c'est un peu à reculons que l'on retourne à l'ancien système 
[1] Nous ne créons pas de route pour le moment, même si ce serait là une bonne pratique, afin de ne pas surcharger inutilement le contenu de ce tutorial, déjà bien assez dense comme ça 
[2] On aurait bien entendu pu proposer des valeurs par défaut.
[3] Le mécanisme de génération de code devrait permettre de proposer facilement la même fonctionnalité pour Doctrine prochainement.
[4] Je vous laisse le soin de vous référer au tutoriel existant sur ce même blog 
Le DrupalCampParis2 se déroulera le 19 avril 2008 à l'espace La Cantine, 151 rue Montmartre, Passage des Panoramas, 12 Galerie Montmartre, 75002 Paris. http://barcamp.org/DrupalCampParis2
Le DrupalCampParis2 se déroulera le 19 avril 2008 à l'espace La Cantine, 151 rue Montmartre, Passage des Panoramas, 12 Galerie Montmartre, 75002 Paris.
Un BarCamp est une rencontre d'un week-end, une non-conférence ouverte qui prend la forme d'ateliers-événements participatifs où le contenu est fourni par les participants qui doivent tous, à un titre ou à un autre, apporter quelque chose au Barcamp. C'est le principe "pas de spectateur", "tous participants". L'événement met l'accent sur les toutes dernières innovations en matière d'applications internet, de logiciels libres et de réseaux sociaux.
SiliconSentier fournit l'espace (LaCantine) AF83 se charge de l'organisation.
Pour vous inscrire et plus de détails allez voir sur: http://barcamp.org/DrupalCampParis2
Proposé par Ori Pekelman
Dans la liste des tâches nouvellement ajoutées en Symfony 1.1, on remarque une section dédiée à l'internationalisation :
i18n :extract Extracts i18n strings from php files :find Finds non "i18n ready" strings in an application
Et oui, la fonctionnalité dont tous les gens qui ont un jour travaillé sur des applications internationalisées en Symfony 1.0 ont rêvé a enfin été ajoutée : une tâche d'extraction des chaînes de caractères à traduire, avec génération et mise à jour des fichiers de traductions XLIFF 
Si vous avez suivi les précédents tutoriels, vous devez disposer d'un projet sf11test, d'une application main et d'un module contact.
On va activer la gestion de l'internationalisation dans l'application en éditant le fichier de configuration apps/main/config/settings.yml comme suit :
[...]
all:
[...]
.settings:
[...]
i18n: on
[...]
standard_helpers: [Partial, Cache, Form, I18N]
[...]
default_culture: en
On part du principe que la langue par défaut sera l'anglais (en). Ajoutons quelques chaînes internationalisées dans le template apps/main/modules/contact/templates/indexSuccess.php au moyen du helper __() :
<h2><?php echo __('Contact us') ?></h2> <p><?php echo __('Drop us a message using the form below:') ?></p> <form action="<?php echo url_for('contact/index') ?>" method="post"> <table> <?php echo $form ?> <tr> <td></td> <td><input type="submit" value="<?php echo __('Send your message') ?>" /></td> </tr> </table> </form>
Maintenant, lançons la commande d'extraction des chaînes à traduire pour notre future version française, en lui demandant poliment de générer automatiquement le fichier de traduction et de supprimer automatiquement les entrées orphelines :
$ ./symfony i18n:extract --auto-save --auto-delete main fr >> i18n extracting i18n strings for the "main" application >> i18n found "3" new i18n strings >> i18n found "0" old i18n strings >> i18n saving new i18n strings >> i18n deleting old i18n strings
Le fichier apps/main/i18n/fr/messages.xml a été généré, examinons son contenu :
<?xml version="1.0"?> <xliff version="1.0"> <file source-language="EN" target-language="fr" datatype="plaintext" original="messages" date="2008-03-13T11:13:45Z" product-name="messages"> <body> <trans-unit id="1"> <source>Contact us</source> <target></target> </trans-unit> <trans-unit id="2"> <source>Drop us a message using the form below:</source> <target></target> </trans-unit> <trans-unit id="3"> <source>Send your message</source> <target></target> </trans-unit> </body> </file> </xliff>
Il ne nous reste plus qu'à traduire nos chaînes en remplissant les balises <target></target> en conséquence pour traduire notre application en français. Si l'on venait à modifier notre template en supprimant, modifiant ou ajoutant de nouvelles chaînes, la tâche d'extraction se chargerait de mettre à jour nos fichiers de traduction en conséquence, tout en préservant le travail déjà effectué 
Je viens de mettre en ligne la version française de Symfonians[1]. J'ai préféré utiliser un sous-domaine pour définir la langue courante plutôt qu'un paramètre supplémentaire dans la requête, car le routing de Symfony implique de le gérer pour chacune des route (ou si y'a une astuce, je suis preneur.)
Ici, je détecte le sous domaine et en fait la langue courante de l'utilisateur au moyen d'un filtre. Pour ceux que ça intéresse, en voici le code :
<?php class i18nSubdomainFilter extends sfFilter { public function execute($filterChain) { if ($this->isFirstCall()) { $context = $this->getContext(); $request = $context->getRequest(); $host_parts = explode('.', $request->getHost()); if (count($host_parts) > 2) // We have at least a subdomain { $subdomain = strtolower($host_parts[0]); $enabled_cultures = sfConfig::get('app_cultures_enabled', array()); if (array_key_exists($subdomain, $enabled_cultures)) { sfConfig::set('sf_current_culture', $subdomain); $context->getResponse()->addMeta('language', $subdomain, true); $context->getUser()->setCulture($subdomain); } } } $filterChain->execute(); } }
Notez que je définis la liste des langues disponibles dans le fichier app.yml, pour éviter les blagues et gérer les domaines pour chacun des environnements que j'ai configuré[2] :
prod:
cultures:
enabled:
en: http://symfonians.net/
fr: http://fr.symfonians.net/
L'activation du filtre se fait dans le fichier filters.yml :
i18nSubdomain: class: i18nSubdomainFilter
Et roule ma poule, mon routing reste strictement intact 
Si vous allez sur le site de http://www.shopalize.com en ce moment il y a des chances que vous voyez ceci:
J'en profite pour rappeler qu'il est impératif de mettre la directive display_errors à "off" et mettre en place un fichier de log via error_log à la place.
Si vous allez sur le site de http://www.shopalize.com en ce moment il y a des chances que vous voyez ceci:
J'en profite pour rappeler qu'il est impératif de mettre la directive display_errors à "off" et mettre en place un fichier de log via error_log à la place.
Si vous allez sur le site de http://www.shopalize.com en ce moment il y a des chances que vous voyez ceci:
J'en profite pour rappeler qu'il est impératif de mettre la directive display_errors à "off" et mettre en place un fichier de log via error_log à la place.
PHP et MySQL ne font l'objet d'aucune alerte de sécurité dans leurs versions courantes :
PHP 5.2.5 et 4.4.8; MySQL 5.0.51 (communauté) , 5.1.23-rc et 6.0.4.
Les mises à jour sont recommandées vers ces versions.
12 alertes de sécurité ont été émises cette semaine, concernant des applications suivantes :
Drupal, Gallery, Horde, Invision Power Board, Joomla, Mantis, PHP Nuke, Smarty, WordPress, Xoops, phpBB et phpMyAdmin
Ces vidéos sont publiés sur les sites de partagent de vidéo. Ce sont des tutoriels enregistrés, des sessions de conférences, des screencast ou encore des slides de conférences.
N'hésitez pas à nous contacter pour signaler tout media qui mérite d'être ajouté à cette liste.
I N V I T A T I O N
Soirée MySQL-Sun Community
Mercredi 2 avril 2008 à PARIS
Afin de célébrer la fusion Sun-MySQL, une série de rencontres avec la communauté est organisée dans de nombreuses capitales mondiales.
En France l'événement aura lieu le 2 avril à Paris. Cette rencontre festive permettra à l’ensemble des développeurs de la communauté open source d’échanger autour des aspects techniques de la fusion et de rencontrer quelques VP Sun-MySQL.
Cette rencontre aura lieu de 18h00 à 23h00 :
Patricks Irish Pub,
33 rue de Montreuil, Paris 11ème
( à 5 mn de Bastille et Gare de Lyon – Ligne 8, Metro Faidherbe-Chaligny )
-- OPEN BAR de 18h00 à 20h00 --
PAF : GRATUIT
Venez nombreux !
Dress c o d e : very casual
*** RSVP avant le 21 Mars à vloquet@alx-communication.com
Pour tout renseignement, tel. : 06 68 42 79 68
Proposé par AL'X Communication
Deux nouveaux podcasts enregistrés lors du Forum PHP 2007 viennent de sortir !
C'est comme toujours par ici:
http://feeds.feedburner.com/forumphp2007
Une invitation a été lancée pour la fusion Sun-MySQL. L'auteur de "Construisez votre application : PHP & MySQL - MySQLi - PDO" sera présent pour cet événement alors pourquoi pas vous ?
Afin de célébrer la fusion Sun-MySQL, une série de rencontres avec la communauté est organisée dans de nombreuses capitales mondiales.
Deux nouveaux podcasts enregistrés lors du Forum PHP 2007 viennent de sortir !
C'est comme toujours par ici:
http://feeds.feedburner.com/forumphp2007
Ces vidéos sont publiés sur les sites de partagent de vidéo. Ce sont des tutoriels enregistrés, des sessions de conférences, des screencast ou encore des slides de conférences.
N'hésitez pas à nous contacter pour signaler tout media qui mérite d'être ajouté à cette liste.
Un problème avec le canal PEAR vient d'être corrigé, la commande plugin-install installait des anciennes versions de plugins au lieu des dernières.
Afin d'y remédier, le plus simple sera de mettre à jour chaque plugin via la commande :
> php symfony plugin-upgrade symfony/myPluginNamePlugin
La commande suivante vous listera vos plugins installés :
> php symfony plugin-list
Retrouvez l'article sur le blog symfony
PHP et MySQL ne font l'objet d'aucune alerte de sécurité dans leurs versions courantes :
PHP 5.2.5 et 4.4.8; MySQL 5.0.51 (communauté) , 5.1.23-rc et 6.0.4.
Les mises à jour sont recommandées vers ces versions.
8 alertes de sécurité ont été émises cette semaine, concernant des applications suivantes :
Gallery, Invision Power Board, Joomla, PHP Nuke, PostNuke, WordPress, Xoops et phpMyAdmin
Voici quelques semaines, nous parlions d'un record de pyramide avec des petits ElePHPants PHP comprenant 8 niveaux avec 36 ElePHPants... Vous pouvez la revoir en cliquant ici.
Pendant les conférences PHP Quebec, qui s'est déroulé du 12 au 14 mars, il a été créé une nouvelle catégorie de pyramide avec des gros ElePHPants. Il a été réalisé une pyramide avec les 15 derniers gros éléPHPants PHP.
Pour voir la réalisation, elle se trouve disponible sur le site de Nexen.net ou directement sur le lien suivant : cliquez iciNous leur disons BRAVO.
Par ailleurs, vous pouvez voir les autres photos de cet évènement.
Tout est dans le titre, je viens de mettre en place une instance Trac/SVN dédiée au projet, le code est libéré et publié sous licence CC-BY-SA 3.0.
Je pense que la publication du code source de l'application est essentiellement utile dans le cadre d'un apprentissage de Symfony, le code étant tout de même très orienté métier.
Edit : Rapido, un petit screencast d'installation de Symfonians à partir des sources depuis subversion :
Télécharger le screencast (QuickTime MOV, ~88 Mo)
Deux mois après la précédente version, le framework Symfony 1.0.12 vient de sortir.
De nombreuses corrections ont été apportées (plus de 30 tickets clôturés) concernant notamment d'importants problèmes de sécurité et de plugins sous Windows, correction de la barre d'outils de débogage utilisant Xdebug, du générateur d'admin...
Il vous est fortement conseillé de mettre à jour vos projets.
Retrouvez le ChangeLog
SELECT bribes.senator_name FROM mafia_projects LEFT JOIN bribes ON (YEAR(mob_projects.bribe_given) = bribes.date_taken) WHERE secret_field = 'secret_value'
SELECT char_field (width 20; not null; no index) FROM myisam_table (size 500, row_format: fixed) LEFT JOIN innodb_table (size 100) ON (YEAR(date_field(not null)) = int_field WHERE enum_field = valid_value_from_enum
Version 6.7 of the Asbru Web Content Management system for PHP, ASP and JSP/Java has been released.
The new version 6.7 of the Asbru Web Content Management system expands the system's e-commerce and access restriction capabilities.
E-Commerce Features Expanded
In this latest release 6.7 of the Asbru Web Content Management system it is now possible to export details about orders and items included in each order directly from the system's GUI. The new version of the system also enables an extended set of user account details to be displayed to registered users. These details include the user's registered delivery details, invoice details and many more.
Access Restriction Capabilities Expanded
The new version of the Asbru Web Content Management system also includes improved handling of website-wide access restrictions. In particular access restriction configuration options have been added to enable access permissions to be inherited between different roles. For example you may choose whether a user with access to publish should also have access to view and update the content as well.
In addition to the enhancements listed above the new version includes a number of minor enhancements:
* Display/output of data from external databases.
* Formatted display of additional date/time attributes.
* Improved RSS channel extension.
* Improved Google/search engine sitemap extension.
For an online trial of the new version of the Asbru Web Content Management system: http://wcm.asbrusoft.com.
About Asbru Web Content Management
The Asbru Web Content Management system is a full-featured and ready to use out-of-the-box enterprise level solution. It is available for PHP, ASP and JSP/Java and runs on Microsoft Windows, Linux, Unix and Mac OS X. The system enables users to update web content through Internet Explorer, Mozilla/Firefox and Safari web browsers. For more information about Asbru Web Content Management: http://wcm.asbrusoft.com.
Proposé par David Fisher
Ces vidéos sont publiés sur les sites de partagent de vidéo. Ce sont des tutoriels enregistrés, des sessions de conférences, des screencast ou encore des slides de conférences.
N'hésitez pas à nous contacter pour signaler tout media qui mérite d'être ajouté à cette liste.

Apéro PHP lillois, le mardi 15 avril 2008
Le prochain Apéro PHP à Lille est prévu pour le 15 avril 2008. Rendez-vous à 19h30 au Café Citoyen - 7 place du vieux marché aux chevaux, près du métro République.
Inscriptions : aperophp
Pour la Belgique, faute de temps avec le déménagement, j'ai un peu oublié l'apéro php de mars. On le fera donc à Leuven, le vendredi 4 avril, au
Café des sports (comme pour les meeting mysql)
Inscriptions : en commentaire sur ce blog ou sur aperophp ou sur facebook : c'est là que ca se passe.
Ca sera l'occasion de parler de phpbelgium

Il y a 2 entrées

Plus d'info sur les apéros PHP belges de 2008 ici
PHP et MySQL ne font l'objet d'aucune alerte de sécurité dans leurs versions courantes :
PHP 5.2.5 et 4.4.8; MySQL 5.0.51 (communauté) , 5.1.23-rc et 6.0.4.
Les mises à jour sont recommandées vers ces versions.
6 alertes de sécurité ont été émises cette semaine, concernant des applications suivantes :
Gallery, Invision Power Board, Joomla, Smarty, e107 et phpBB
Get the Flash Player to see this player.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Ajax</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<div>
Hello world.
{
}
<input type="button" onclick="doPost();" value="doPost"/>
<input type="button" onclick="doGet();" value="doGet"/>
<input type="button" onclick="doPostGet();" value="doGet + doPost"/>
<hr/>
<div id="responsePost" style="float:left"></div>
<div id="responsePostGet" style="float:left;margin-left:300px"></div>
<div id="responseGet" style="float:right"></div>
</div>
<script type="text/javascript">
//<![CDATA[
//Objet Ajax à instancier
var Ajax = function()
{
var current = this;
this.xhr = Ajax.getXhr();
this.ondone = function(data){ /* debug */ };
this.post = function(strUrl, strArgs)
{
this.xhr.open('POST', strUrl);
this.xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset:UTF-8');
this.xhr.onreadystatechange = function()
{
if(current.xhr.readyState == 4 && current.xhr.status == 200)
current.ondone(current.xhr.responseText);
};
this.xhr.send(strArgs); //arg1=value1&arg2=value2...
};
this.get = function(strUrl)
{
this.xhr.open('GET', strUrl); //http://domain/script.php?arg1=value&arg2=va%20lue2...
this.xhr.onreadystatechange = function()
{
if(current.xhr.readyState == 4 && current.xhr.status == 200)
current.ondone(current.xhr.responseText);
};
this.xhr.send();
};
}
//Méthode Static
Ajax.getXhr = function()
{
if(window.XMLHttpRequest)
{
return new XMLHttpRequest();
}
else if(window.ActiveXObject)
{
try
{
return new ActiveXObject('Msxml2.XMLHTTP');
}
catch(e)
{
try
{
return new ActiveXObject('Microsoft.XMLHTTP');
}
catch(e)
{
throw new Error('XMLHTTP not found');
}
}
}
}
function doPost()
{
var a = new Ajax();
a.ondone = function(data)
{
document.getElementById('responsePost').innerHTML = data;
};
a.post('index.php' , 'a=1&b=2');
}
function doGet()
{
var a = new Ajax();
a.ondone = function(data)
{
document.getElementById('responseGet').innerHTML = data;
};
a.get('index.php?a=1&b=2&c=3');
}
function doPostGet()
{
var a = new Ajax();
a.ondone = function(data)
{
document.getElementById('responsePostGet').innerHTML = data;
};
a.post('index.php?arg1=value1&arg2=value2' , 'a=1&b=2');
}
//]]>
</script>
</body>
</html>
Et le fichier php :
<?php
header('Content-Type: text/html; charset=UTF-8');
echo 'POST :<pre>';
print_r($_POST);
echo '<pre>';
echo 'GET :<pre>';
print_r($_GET);
echo '<pre>';
echo 'Requête effectuée';
Voici un tutorial que j’ai réalisé en premier lieu sur le forum de support OVH. Il s’adresse à toute personne souhaitant mettre en place un server dédié, qu’il soit chez OVH ou non, qu’il soit sous Slackware ou non (je n’utiliserai “le” système de package propre à Slackware uniquement pour installer des librairies, outils de compilation et pour la mise à jour du système. La majorité des installations propre au “serveur web” seront détaillées et effectuées via configure/make/make install qui est la base commune à tous les Linux).
Le nom host du serveur donné ici sera ns10000.
Premières vérifications qui peuvent éviter quelques soucis dans un futur proche (problèmes réellement rencontrés) :
#ping ns10000 ping: unknown host ns10000
En fait le fichier host était bancal (ça commencait mal
) :
#cat /etc/hosts 127.0.0.1 localhost 91.121.14.48 2-ns10000.ovh.net ns10000
On corrige en (avec vi ou en ramenant ça chez soi en sftp, on installe nano dès qu’on peut) :
127.0.0.1 localhost 91.121.14.48 ns10000.ovh.net ns10000
#date
La date était elle aussi en retard de deux mois.
Premier problème rencontré :
Mettre à jour la date du serveur en l’enregistrant dans le bios grâce à la commande hwclock ne marche pas.
#hwclock –show select() to /dev/rtc to wait for clock tick timed out
#hwclock –systohc –debug hwclock from util-linux-2.12p Using /dev/rtc interface to clock. Last drift adjustment done at 1137365083 seconds after 1969 Last calibration done at 1137365083 seconds after 1969 Hardware clock is on UTC time Assuming hardware clock is kept in UTC time. Waiting for clock tick… select() to /dev/rtc to wait for clock tick timed out …got clock tick
#hwclock –set –date=”09/11/07 13:56:00″ –utc –debug Issuing date command: date –date=”09/11/07 13:56:00″ +seconds-into-epoch=%s response from date command = seconds-into-epoch=1189511760 date string 09/11/07 13:56:00 equates to 1189511760 seconds since 1969. hwclock from util-linux-2.12p Using /dev/rtc interface to clock. Last drift adjustment done at 1137365083 seconds after 1969 Last calibration done at 1137365083 seconds after 1969 Hardware clock is on UTC time Assuming hardware clock is kept in UTC time. Waiting for clock tick… select() to /dev/rtc to wait for clock tick timed out …got clock tick
select() to /dev/rtc to wait for clock tick timed out
Une recherche sur Google nous indiquera qu’il existe un bug avec les Intel dualcore et que l’on peut contourner le problème en utilisant l’option “–directisa” avec hwclock
#hwclock –help | grep directisa –directisa access the ISA bus directly instead of /dev/rtc
Autant vous dire tout de suite que ca ne marchera pas mieux
(bus isa inexistant ?)
root@ns10000:/# hwclock –show –directisa root@ns10000:/#
et que jusqu’à présent je n’ai pas trouvé comment enregistrer dans le bios du serveur la bonne date. Je suis donc obligé de la mettre à jour à chaque (rare) reboot (grâce à NTP que nous verrons plus loin)
Nano est très pratique et on en a tout le temps besoin. Installons le en priorité
root@ns10000:/home# wget http://repository.slacky.eu/slackwar…6-i486-1sl.tgz
root@ns10000:/home# installpkg nano-2.0.6-i486-1sl.tgz
Afin de se logger avec un autre utilisateur que root, on crée un nouvel utilisateur (ici “toto”)que l’on n’oublie pas de placer dans le groupe wheel (pour pouvoir se logger en root depuis cet user) :
# useradd -g users -G wheel -s /bin/bash toto # passwd toto
Une fois effectué, tenter de vous connecter en SSH avec cet utilisateur, puis de vous loggeur en root.
Attention, les modifications suivantes empecheront les techs OVH d’accèder à votre serveur. A vos risques et périls de les effectuer
On change le port par défaut pour éviter une bonne partie de scan, on interdit au root de se connecter directement (on se connectera avec l’utilisateur “toto”)
/etc/ssh/sshd_config
Port 8655 PermitRootLogin no PermitEmptyPasswords no AllowUsers toto SyslogFacility AUTH LogLevel INFO
On restart (et on ne stop surtout pas !) le démon :
root@ns10000:/etc/rc.d# ./rc.sshd restart
Vous vous connecter maintenant en utilisant votre nouvel utilisateur non root sur le nouveau port.
| #cd /home/
#wget http://heanet.dl.sourceforge.net/sou…1-noarch-2.tgz #installpkg slackpkg-2.61-noarch-2.tgz |
On désactive la vérification GPG (GPG n’est pas installé pour le moment (on évite ainsi le message de rappel récurrent suivant à chaque fois qu’on utilise slackpkg) :
gpg package not found! Please disable GPG in /etc/slackpkg/slackpkg.conf or install the gnupg package. To disable GPG, edit slackpkg.conf and change the value of the CHECKGPG variable to off - you can see an example in the original slackpkg.conf.new file distributed with slackpkg.
On active un des miroirs des paquets slackware-10.2 en décommantant une des lignes du michier mirrors :
/etc/slackpkg/mirrors
http://ftp.belnet.be/packages/slackware/slackware-10.2/
Note : On peut tout a fait passer en slackware 12, cependant certaine mise à jour touchant au coeur du système sont à faire avec précaution. Dans ce tutorial nous restons en Slackware 10.2
On peut maintenant mettre à jour la liste interne des paquets de slackpkg :
#slacpkg update
Et ensuite demander la liste des paquets upgradables :
#slackpkg upgrade-all
http://hiboox.com/lang-fr/image.php?img=xu81a9er.png
A vous ensuite de choisir quels paquets vous souhaitez mettre à jour.
Utilisons l’outil de package de la distribution pour récupérer les compilateurs et dépendances nécessaires par la suite.
Dans un premier temps regardons ce qui est installé :
# slackpkg search glib The list below shows all packages with the selected pattern. … [ installed ] - glibc-solibs-2.3.5-i486-6_slack10.2 [ installed ] - glibc-zoneinfo-2.3.5-noarch-8_slack10.2 [uninstalled] - glib-1.2.10-i386-2 [uninstalled] - glib2-2.6.6-i486-1 [uninstalled] - glibc-2.3.5-i486-5 [uninstalled] - glibc-i18n-2.3.5-noarch-5 [uninstalled] - glibc-profile-2.3.5-i486-5
Nous pouvons ainsi installer :
# slackpkg install glib # slackpkg install glib2 # slackpkg install glibc
Idem pour gcc :
# slackpkg install gcc
# slackpkg search gcc The list below shows all packages with the selected pattern. [ installed ] - gcc-4.1.2-i486-1 [ installed ] - gcc-g++-4.1.2-i486-1 [uninstalled] - gcc-gfortran-4.1.2-i486-1 [uninstalled] - gcc-gnat-4.1.2-i486-1 [uninstalled] - gcc-java-4.1.2-i486-1 [uninstalled] - gcc-objc-4.1.2-i486-1 [uninstalled] - gcc-g77-3.4.6-i486-1
Les outils de compilation sont installés. Ils nous manque plus que les kernels-headers aussi nécessaires. Nous allons télécharger les sources complètes du noyau de la machine qui les contient (et nous pourrons ainsi envisager ultérieurement de toucher au noyau).
Tout d’abord enlevons les éventuels kernel-headers/sources déjà installés et qui ne sont pas forcément ceux du noyau sur lequel vous êtes (slackware 10.2 est prévu pour tourner sur un noyau 2.4.32, vous disposez alors des kh/s 2.4.32 dans les dépots unqiuement. Si vous êtes passé en slackware 12, vous aurez les kh/s 2.6.21.5):
Noyau de la machine :
# uname -r 2.6.21.5-grsec-xxxx-grs-ipv4-32
#slackpkg remove kernel-headers #slackpkg remove kernel-source
Est ce propre ?
cd /usr/src/ && ls -lh
devrait etre vide, sinon faite un peu de nettoyage
Dl des sources complètes relatives au noyau, décompression et lien symbolique :
root@ns10000:/usr/src# wget http://www.eu.kernel.org/pub/linux/kernel/v2.6/linux-2.6.21.5.tar.gz root@ns10000:/usr/src# tar xvf linux-2.6.21.5.tar.gz root@ns10000:/usr/src# ln -s /usr/src/linux-2.6.21.5 linux
On n’oublie pas :
root@ns10000:/usr/src# cd linux/ root@ns10000:/usr/src# make mrproper
Tant qu’on y on peut préparer le terrain à une futur recompilation du noyau.
# cd /usr/include root@ns10000:/usr/include# ln -s /usr/src/linux/include/linux linux root@ns10000:/usr/include# ln -s /usr/src/linux/include/asm-i386 asm root@ns10000:/usr/include# ln -s /usr/src/linux/include/asm-generic asm-generic
Et voila, nous avons de quoi compiler les logiciels que nous allons utilisez et de toucher aussi à la recompilation du noyau (qui ne sera cependant pas aborder ici)
A titre informatif si vous ne souhaiter pas utiliser les Flags de compilation par défaut :
Cela dépend de votre architecture et de votre version de gcc. Pour les Intel Core 2 Duo et une version de gcc < 4.3 vous pouvez utiliser lors des configure :
# ./configure … CFLAGS=”-march=prescott -O3 -pipe -fomit-frame-pointer”
Pour les futurs gcc (>= 4.3), une nouvelle préselection sera dispo :
# ./configure … CFLAGS=”-march=core2 -O3 -pipe -fomit-frame-pointer”
Vous pouvez déterminer quels sont les bonnes options d’architecture à utiliser grâce au script gcccpuopt :
http://www.pixelbeat.org/scripts/gcccpuopt
Pour enregistrer vos préférences sur le shell courant, vous pouvez enregistrer la valeur des CFLAGS qui sera réutilisée à chaque compilation. Faites de même pour les flags c++ CXXFLAGS
export CFLAGS=”-march=prescott -O3 -pipe -fomit-frame-pointer”
Et en l’enregistrant dans votre fichier /etc/profile pour la conserver définitivement.
# nano /etc/profile
# /etc/profile: This file contains system-wide defaults used by # all Bourne (and related) shells. # Set the values for some environment variables: #[...] export CFLAGS=”-march=prescott -O3 -pipe -fomit-frame-pointer” export CXXFLAGS=”${CFLAGS}” #[...]
Je vous invite à consulter pour une explication de ces options/optimisations :
http://www.linux-kheops.com/doc/man/…an1/gcc.1.html
http://gentoo-wiki.com/Safe_Cflags#I…_51xx. 2F53xx
http://forums.gentoo.org/viewtopic-t…-start-25.html
Je vais compiler ici Apache 2.0.x avec le module mod_deflate qui permet la compression du flux de sortie. Ce module utilise la bibliothèque Zlib qu’il faut donc installer. Nous utilisons slackpkg pour installer cette librairie (la dernière version se trouve sur les miroirs, pas forcément utile de la compiler nous-même)
slackpkg install zlib
On se créer un dossier de compilation où on y désarchive Apache (libre à vous d’installer la version d’Apache que vous souhaiter. N’oubliez pas que pour compiler Apache 2.2 il vous faudra installer APR en version >= 1.0):
root@ns10000:~# mkdir /home/compilation root@ns10000:~# cd /home/compilation root@ns10000:/home/compilation# wget http://apache.fastorama.com/dist/httpd/httpd-2.0.61.tar.gz root@ns10000:/home/compilation# tar xvf httpd-2.0.61.tar.gz root@ns10000:/home/compilation# cd httpd-2.0.61 root@ns10000:/home/compilation/httpd-2.0.61# make clean
Un make clean n’est pas du tout inutile (experience inside) !
C’est à vous de savoir quels modules APache vous souhaitez conserver ou enlever, la compilation suivante n’est donnée qu’à titre indicatif :
root@ns10000:/home/compilation/httpd-2.0.61#./configure –prefix=/usr/local/apache2 –enable-so –enable-deflate –enable-headers –disable-actions –disable-imap –disable-userdir root@ns10000:/home/compilation/httpd-2.0.61#make
On vérifie que Apache s’est compilé avec les bons modules (c’est à votre avantage de ne pas compiler des modules dont vous ne vous servirez jamais) :
root@ns10000:/home/compilation/httpd-2.0.61# ./httpd -l Compiled in modules: core.c mod_access.c mod_auth.c mod_include.c mod_deflate.c mod_log_config.c mod_env.c mod_headers.c mod_setenvif.c prefork.c http_core.c mod_mime.c mod_status.c mod_autoindex.c mod_negotiation.c mod_dir.c mod_alias.c mod_so.c
C’est OK on peut l’installer :
root@ns10000:/home/compilation/httpd-2.0.61# make install
Dans ce tutoriel je ne vais me servir d’Apache uniquement pour traiter du contenu dynamique (PHP). Tout le contenu statique sera distribué par Lighttpd qui fera aussi service de frontal. C’est un couple très efficace niveau performance.
Disons que nous allons hébergés sur ce serveur au moins 2 sites internet indépendants. (site1.com et site2.net)
root@ns10000:/home# groupadd www root@ns10000:/home# useradd httpd -g nogroup -s /bin/false root@ns10000:/home# usermod -L httpd #lock le compte
Le groupe www va nous servir pour le serveur FTP
#mkdir /home/htdocs #mkdir /home/htdocs/site1.com #mkdir /home/htdocs/site2.net
nano /usr/local/apache2/conf/httpd.conf
Vous pouvez modifier les parametres suivants :
User httpd Group nogroup #Nous ne desservons que du PHP, nous pouvons désactiver le keepalive KeepAlive Off #Port 8070 sera destiné au virtualhost pour site1.com Listen 127.0.0.1:8070 #Port 8080 sera destiné au virtualhost pour site2.net Listen 127.0.0.1:8080 DocumentRoot “/home/htdocs” NameVirtualHost 127.0.0.1:8070 NameVirtualHost 127.0.0.1:8080 <VirtualHost 127.0.0.1:8070> DocumentRoot /home/htdocs/site1.com ServerName www.site1.com </VirtualHost> <VirtualHost 127.0.0.1:8080> DocumentRoot /home/htdocs/site2.net ServerName www.site2.net </VirtualHost>
Vous remarquer ici qu’apache n’écoute que sur l’interface locale. En effet nous allons nous servir de Lighttpd comme serveur frontal et utiliser son module mod_proxy pour forwarder les requetes de contenu dynamique vers Apache selon le port qui définira de quel site il s’agit
On va avoir besoin du support du module pcre dans lighttpd pour écrire entre autres nos règles de proxy. Il nous faut l’installer avant d’effectuer la compilation de lighty sinon ca ne marchera pas 
root@ns10000:/home/compilation# wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-7.4.tar.gz root@ns10000:/home/compilation# tar xvf pcre-7.4.tar.gz root@ns10000:/home/compilation# cd pcre-7.4/ root@ns10000:/home/compilation/pcre-7.4/# .configure –help #Choisissez vos options spécifiques ou simplement ./configure root@ns10000:/home/compilation/pcre-7.4/# make && make install
C’est toujours à vous de chosir quoi compiler. Ce sont des exemples pour une utilisation spécifique qui ne vous coniendra pas forcément
root@ns10000:/home/compilation# wget http://www.lighttpd.net/download/lighttpd-1.4.18.tar.gz root@ns10000:/home/compilation# tar xvf lighttpd-1.4.18.tar.gz root@ns10000:/home/compilation# cd lighttpd-1.4.18 root@ns10000:/home/compilation/lighttpd-1.4.18# ./configure –disable-ipv6 –with-bzip2 –with-pcre
–with-bzip2 : Pour pouvoir utilser le module de compression mod_compress (l’équivalent de mod_deflate sous Apache)
Finalement :
root@ns10000:/home/compilation/lighttpd-1.4.18# make && make install
User sous lequel va tourner Lighttpd
root@ns10000:/home# useradd lighttpd -g nogroup -s /bin/false root@ns10000:/home# usermod -L lighttpd #lock le compte
Fichier de log
root@ns10000:/home# cd /var/log/ root@ns10000:/var/log# mkdir lighttpd root@ns10000:/var/log# touch error.log root@ns10000:/var/log# chown lighttpd lighttpd/ root@ns10000:/var/log# chmod 744 lighttpd/
Configuration
nano /etc/lighttpd.conf
#On active les modules que l’on souhaite server.modules = ( “mod_rewrite”, “mod_redirect”, “mod_access”, “mod_status”, “mod_simple_vhost”, “mod_proxy”, “mod_compress”, “mod_expire” ) #Paramètres primaires server.document-root = “/home/htdocs” server.username = “lighttpd” server.groupname = “nogroup” #Mod_compress : mise en place d’un cache de compression sur certain type mime pour éviter de compresser à chaque fois compress.filetype = (”text/html”, “text/plain”, “text/css”, “text/javascript”, “text/xml”) #N’oubliez pas de créer le répertoire et lui donner les bons droits (idem que pour le fichier et répertoire de log) compress.cache-dir = “/home/lighttpd_cache/” #Ce qu’on a fait en haut server.errorlog = “/var/log/lighttpd/error.log” #Trés important, n’envoyez pas vos fichiers php non interprété ! Lighttpd ne dessert ici que le statique et reconnait les fichiers php qu’en tant que texte. static-file.exclude-extensions = ( “.php”, “.inc”, “htaccess”, “htpasswd” ) #Frontal server.port = 80 # #Quelques règles d’exemples # #redirection vers le www $HTTP["host"] =~ “^site1\.com” { url.redirect = (”(.*)” => “http://www.site1.com$1″) } $HTTP["host"] =~ “^site2\.net” { url.redirect = (”(.*)” => “http://www.site2.net$1″) } $HTTP["host"] == “www.site1.com” { server.document-root = “/home/htdocs/site1.com/” #Nous laissons Apache desservir les fichiers index.* Cf. post 8 de dam23 et post 9 $HTTP["url"] == “/” { proxy.server = ( “” => ( ( “host” => “127.0.0.1″, “port” => 8070 ) ) ) } #Forward du contenu dynamique (fichiers php) vers apache proxy.server = ( “.php” => ( ( “host” => “127.0.0.1″, “port” => 8070 ) ) ) } $HTTP["host"] == “www.site2.net” { server.document-root = “/home/htdocs/site2.net/” #Nous laissons Apache desservir les fichiers index.* Cf. post 8 de dam23 et post 9 $HTTP["url"] == “/” { proxy.server = ( “” => ( ( “host” => “127.0.0.1″, “port” => 8080 ) ) ) } proxy.server = ( “.php” => ( ( “host” => “127.0.0.1″, “port” => 8080 ) ) ) }
On lance Lighttpd depuis root. Lighttpd se chargera ensuite de dropper ses privilèges pour obtenir ceux du user “lighttpd” spécifié.
root@ns10000:~# /usr/local/sbin/lighttpd -f /etc/lighttpd.conf root@ns10000:~# ps aux | grep light lighttpd 17972 0.0 0.1 4464 3172 ? S Dec10 0:35 /usr/local/sbin/lighttpd -f /etc/lighttpd.conf
On consulte les éventuelles erreurs de démarrage grâce au fichier de log :
root@ns10000:~# tail /var/log/lighttpd/error.log
Normalement tout devrait être OK

Nous installons MySQL avant PHP car nous avons besoin du package MySQL-devel lors de la compilation de PHP. Autant tout installer en même temps.
Nous allons installer MySQL (Server + Client + devel) à partir des packages RPM fourni par MySQL. J’updaterai ce message pour ajouter une version “compilation du serveur” (à la place d’une installation par package RPM du serveur) et ferai un bench pour comparer ces deux approches d’installation.
Je vous invite à consulter ce lien pour savoir comment sont compilés ces packages RPM :
http://dev.mysql.com/doc/refman/5.0/…-binaries.html
http://dev.mysql.com/doc/refman/5.0/…k-options.html
Nous installons tout d’abord avec slackpkg le gestionnaire RPM pour slackware :
slackpkg install rpm
)root@ns10000:/home/compilation# wget http://dev.mysql.com/get/Downloads/MySQL-5.0/MySQL-server-5.0.45-0.i386.rpm/from/http://mir2.ovh.net/ftp.mysql.com/ root@ns10000:/home/compilation# wget http://dev.mysql.com/get/Downloads/MySQL-5.0/MySQL-client-5.0.45-0.i386.rpm/from/http://mir2.ovh.net/ftp.mysql.com/ root@ns10000:/home/compilation# wget http://dev.mysql.com/get/Downloads/MySQL-5.0/MySQL-devel-5.0.45-0.i386.rpm/from/http://mirrors.ircam.fr/pub/mysql/ root@ns10000:/home/compilation# wget http://dev.mysql.com/get/Downloads/MySQL-5.0/MySQL-shared-5.0.45-0.i386.rpm/from/http://mirrors.ircam.fr/pub/mysql/
Sous Slackware il faut forcer l’installation et bypasser le contrôle des dépendances pour installer correctement un RPM
root@ns10000:/home/compilation# rpm -Uvh –nodeps –force MySQL-server-5.0.45-0.i386.rpm root@ns10000:/home/compilation# rpm -Uvh –nodeps –force MySQL-client-5.0.45-0.i386.rpm root@ns10000:/home/compilation# rpm -Uvh –nodeps –force MySQL-devel-5.0.45-0.i386.rpm root@ns10000:/home/compilation# rpm -Uvh –nodeps –force MySQL-shared-5.0.45-0.i386.rpm
Nous allons effectuer les différentes actions afficher lors de l’installation des RPM
On supprime d’éventuel user/group existant, on met les bon droit sur le répertoire ou sera stocké notre socket (si vous utilisez le socket .sock de mysql bien sûr)
root@ns10000:~# userdel mysql root@ns10000:~# groupdel mysql root@ns10000:~# groupadd mysql root@ns10000:~# useradd -g mysql mysql root@ns10000:~# usermod -d /var/lib/mysql -s /bin/false mysql root@ns10000:~# cd /var/lib root@ns10000:/var/lib# chown -R mysql:mysql /var/lib/mysql
Nous allons placer le répertoire data de MySQL sur /home (qui dispose chez OVH par défaut de 90% de l’espace disque)
root@ns10000:~# mkdir /home/mysql root@ns10000:~# chown mysql:mysql /home/mysql
On configure ensuite my.cnf selon ce que l’on vient d’effectuer. (toutes les options ne sont pas affichées, seulement celles à créer ou modifier)
nano /etc/my.cnf
[client] socket = /var/lib/mysql/mysql.sock [mysqld] long_query_time = 2 datadir= /home/mysql log-warnings=2 log-error=/home/mysql/mysql.log socket = /var/lib/mysql/mysql.sock
On installe les tables par défaut de MySQL
#sh /usr/bin/mysql_install_db
On place un mot de passe root avec mysqladmin
#mysqladmin -u root password ‘motdepasse’
Vous trouverez dans /usr/share/mysql/ le script mysql.server que vous pouvez placer dans /etc/rc.d
Et au final vous pouvez lancer MySQL (ligne de commande en exemple !)
root@ns10000:/etc/rc.d# sh /etc/rc.d/mysql.server start –skip-innodb –skip-bdb –log-warnings=2 & root@ns10000:/etc/rc.d# Starting MySQL SUCCESS!
C’est tellement bien quand ça marche directement

root@ns10000:~# slackpkg install libxml root@ns10000:~# slackpkg install libxml2 root@ns10000:~# slackpkg install libpng
Si la compilation vous manque et que vous voulez les dernières versions de libcurl et libjpeg (non à jour sur les dépots 10.2) :
root@ns10000:/home/compilation# wget http://curl.haxx.se/download/curl-7.17.1.tar.gz && cd curl-7.17.1 && ./configure && make && make install root@ns10000:/home/compilation# wget ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz && jpegsrc.v6b && ./configure –enable-static –enable-shared –prefix=/usr && make && make install
Toujours en exemple, ne compiler que ce dont vous avez besoin !
root@ns10000:/home/compilation# wget http://fr3.php.net/get/php-5.2.5.tar.gz/from/fr.php.net/mirror root@ns10000:/home/compilation# tar xvf php-5.2.5.tar.gz && cd php-5.2.5 root@ns10000:/home/compilation/php-5.2.5# ./configure –prefix=/usr/local/php5 –with-apxs2=/usr/local/apache2/bin/apxs –with-mysql=/usr/lib/mysql –with-libxml-dir=/usr/local/lib –with-gd –with-curl –with-zlib-dir –with-png-dir –with-jpeg-dir –without-sqlite –enable-ftp –enable-zip –enable-sockets –enable-exif –enable-mbstring –disable-ipv6 –disable-cgi –disable-short-tags root@ns10000:/home/compilation/php-5.2.5# make && make test
Une fois les tests effectués on peut installer et suivre scrupulesement les indications d’installation (si la modification de httpd.conf a réussie etc …):
root@ns10000:/home/compilation/php-5.2.5# make install
L’installeur de PHP a normalement été à même de détecter et d’ajouter à la configuration Apache le nécessaire à l’interprétation des fichiers PHP. Vous devez disposez maintenant des lignes suivantes dans /usr/local/apache2/conf/httpd.conf
LoadModule php5_module modules/libphp5.so #apache ne sert pas de statique, mais nous l’utilisons pour desservir les fichiers index DirectoryIndex index.html index.php AddType application/x-httpd-php .php
Note : Cf. post #8 et #9 : Pour récuperer l’adresse IP du client dans les scripts PHP, il ne faut pas utiliser la variable $_SERVER['REMOTE_ADDR'] mais $_SERVER['HTTP_X_FORWARDED_FOR'] car $_SERVER['REMOTE_ADDR'] aura pour valeur 127.0.0.1 étant donné que la requête traité par Apache (et donc par le script) provient de Lighttpd.
Vous pouvez ensuite configurer votre php.ini puis installer ZendOptimizer par exemple
Vous devez lancer Apache en root, il droppera lui même les privilèges root pour garder ceux du user “httpd”
root@ns10000:~# cd /usr/local/apache2/bin root@ns10000:/usr/local/apache2/bin# ./apachectl start root@ns10000:/usr/local/apache2/bin#
Ensuite consulter les éventuelles erreurs de démarrage dans le fichier de log :
root@ns10000:/usr/local/apache2/bin# cd ../logs root@ns10000:/usr/local/apache2/bin# tail error_log [Mon Dec 31 14:24:54 2007] [notice] Apache configured — resuming normal operations
Normalement tout devrait être OK.
Je vous propose d’installer proFTPD, d’y créer un superadmin “ftp_admin” ayant tout pouvoir sur tout htdocs/, un admin “ftp_admin_site1″ qui aura tout pouvoir sur htdocs/site1.com, et de paramétrer les autorisations d’accès
root@ns10000:~# cd /home/compilation/ root@ns10000:/home/compilation# wget ftp://ftp.proftpd.org/distrib/source/proftpd-1.3.1.tar.gz root@ns10000:/home/compilation# tar xvf proftpd-1.3.1.tar.gz root@ns10000:/home/compilation# cd proftpd-1.3.1 root@ns10000:/home/compilation# ./configure –help #faites vos choix de compilation ou configurer directement pour les choix par défaut root@ns10000:/home/compilation# make && make install
ProFTPd nécessite un shell valide pour que les utilisateurs puissent se connecter. Un shell “est valide” si il figure dans le fichier /etc/shells
root@ns10000:~#cat /etc/shells /bin/bash root@ns10000:~#
Nos utilisateurs “ftp_admin” et “ftp_admin_site1″ auront pour shell /bin/false, il faut donc rajouter ce shell :
root@ns10000:~# echo “/bin/false” >>/etc/shells
Sinon nous aurions eu l’erreur suivante lors du login :
227.w86-198.abo.wanadoo.fr[86.198.198.198]): USER ftp_admin (Login failed): Invalid shell: ‘/bin/false’
root@ns10000:~# groupadd ftpusers root@ns10000:~# useradd -s /bin/false -d /home/htdocs/ -g ftpusers ftp_admin root@ns10000:~# passwd ftp_admin root@ns10000:~# useradd -s /bin/false -d /home/htdocs/site1.com -g ftpusers ftp_admin_site1 root@ns10000:~# passwd ftp_admin_site1
Attention ! un shell sur /bin/false empeche le login via SSH, mais n’empeche pas d’utiliser des outils non shell : authentification, portforwarding etc …
Donc on rajoute explicitement dans notre fichier sshd_config :
nano /etc/ssh/sshd_config
DenyUsers ftp_admin, ftp_admin_site1
Ce fichier contient la liste des utilisateurs étant banni de login via FTP.
Par défaut on ajoute tout le monde présent sur le système (via les logins présents dans /etc/passwd), on rajoute aussi anonymous, mais on enlève ftp_admin et ftp_admin_site1
root@ns10000:~# cat /etc/passwd | cut -f1 -d: > /etc/ftpusers root@ns10000:~# echo anonymous >> /etc/ftpusers root@ns10000:~# nano /etc/ftpusers #Enlever les users FTP root@ns10000:~# cat /etc/ftpusers root bin daemon adm lp sync shutdown halt mail news uucp operator games smmsp rpc sshd gdm pop nobody anonymous … etc
Extrait de configuration à modifier/ajouter
root@ns10000:~# nano /etc/proftpd.conf
| ServerName “ns1000-FTP”
ServerType standalone DefaultServer on # Set the user and group under which the server will run. User nobody Group nogroup SystemLog /var/log/proftpd.log #To cause every FTP user to be “jailed” (chrooted) into their home DefaultRoot ~ # Autoriser l’usage de /etc/ftpusers UseFtpUsers on # Bar use of SITE CHMOD by default <Limit SITE_CHMOD> DenyAll </Limit> # Configuration des users <Directory /home/htdocs> <Limit WRITE> AllowUser ftp_admin DenyAll </Limit> <Limit READ> AllowUser ftp_admin DenyAll </Limit> </Directory> <Directory /home/htdocs/site1.com> <Limit WRITE> AllowUser ftp_admin AllowUser ftp_admin_site1 DenyAll </Limit> <Limit READ> AllowUser ftp_admin AllowUser ftp_admin_site1 DenyAll </Limit> </Directory> |
Bien sur cela dépend de votre installation et de vos besoins ! Ceci n’est qu’à titre indicatif !
Qui est le propriétaire ? ftp_admin : rwX (x que sur les dossiers et non les fichiers)
Qui est le groupe ? ftpusers : rwX
Que doit pouvoir faire Lighttpd/Apache : Lire (écrire pour certain script PHP ?) : rX
root@ns10000:/home/htdocs# chown -R ftp_admin:ftpusers * root@ns10000:/home/htdocs# chmod -R u=rwX,g=rwX,o=r-X *
A vous de spécifier les droits précis sur les répertoires qui doivent être accessible en écriture par Apache 