#########  Sub0 - Developpez.com - 23/09/06
 

INTRODUCTION

Apparemment, un grand nombre d'hébergeurs web ne permettent plus l'accès direct aux bases de données avec des composants SGBD Delphi; La solution que j'ai adopté est d'utiliser des scripts PHP, hébergés sur le même serveur que la base de données et d'exécuter ces scripts avec un programme Delphi.

Ce tutoriel est destiné à vous montrer comment j'utilise un composant d'accès Http pour exécuter des scripts PHP avec Delphi et pouvoir accéder aux bases de données MySQL. Ce tutoriel contient également le code source d'un espace membre très complet pour sécuriser l'accès de la base et une démo d'administration des données MySQL, ainsi que toutes les informations nécessaires pour installer les scripts et configurer ces programmes.
 

«DELPHP»

J'ai baptisé ce projet DELPHP. Son principal avantage par rapport aux composants SGBD est qu'il n'est pas nécessaire de fournir le login d'accès de la base de données dans le programme Delphi. Il n'est pas nécessaire non plus d'installer de nouveau composant dans la palette de Delphi. Toutes les sources sont disponibles gratuitement. Le principe est le même qu'un navigateur web.

Pour exécuter les scripts PHP, j'utilise le composant
THttpCli d'ICS. J'ai récupéré le code de ce composant (3 unités) afin de pouvoir l'utiliser dynamiquement dans mes projets. Ainsi, cela vous évitera l'installation de toute la palette d'ICS juste pour compiler les démos.

Pour simplifier son utilisation, j'ai réalisé une Class nommée
THttpPost dans l'unité DelphpUnit.pas. Cette Class permet de communiquer avec les scripts PHP. Le code suivant vous montre comment je l'utilise pour simuler le Post d'un formulaire, plus précisément, poster 3 champs de saisie texte vers le script "connect.php" de mon serveur local :

Uses DelphpUnit...;

...

Var
  Form1: TForm1;
  HttpPost1: THttpPost;


{----------------------------------------------------------------}
Procedure TForm1.FormCreate(Sender: TObject);
Begin
  
{ Création dynamique du composant }
  HttpPost1 := THttpPost.Create(self);
  HttpPost1.URL :=
'http://127.0.0.1/connect.php';
  HttpPost1.ProxyPort :=
'80';
  HttpPost1.MaxTimeOut := 10000;
End;


{----------------------------------------------------------------}
Procedure TForm1.Button1Click(Sender: TObject);
Begin
  
{ Préparation de la requête http }
  HttpPost1.ResetPost;
  HttpPost1.AddPost(
'pseudo', 'sub0');
  HttpPost1.AddPost(
'email', '');
  HttpPost1.AddPost(
'mdp', 'test');

  
{ Post de la requête http }
  HttpPost1.StartPost;

  
{ Boucle d'attente de fin de réception }
  Repeat
    Application.ProcessMessages;
    Sleep(50);
  Until (HttpPost1.IsCompleted);

  
{ Affichage du résultat (message d'erreur) }
  If
(HttpPost1.StringError <> '') Then
    ShowMessage(HttpPost1.StringError)
  Else
  
{ Affichage du résultat du formulaire }
  If
(HttpPost1.StringResult <> '') Then
    ShowMessage(HttpPost1.StringResult);
End;  

Post du formulaire avec DELPHI :
La méthode
ResetPost sert à effacer la liste des champs de saisie.
La méthode
AddPost, à ajouter chaque champs de saisie.
Note : Vraisemblablement, la taille d'une requête Http est limitée à 8Mo maximum.


Réception du formulaire avec PHP :
La réception des champs de saisie postés avec Delphi se fait de façon tout à fait normale avec le tableau $_POST. Sur le serveur, le script
connect.php réceptionne les données comme ceci :

<?php
$
pseudo=''If(isset($_POST['pseudo'])) $pseudo=$_POST['pseudo'];
$email=''; If(isset($_POST['email'])) $email=$_POST['email'];
$mdp=''If(isset($_POST['mdp'])) $mdp=$_POST['mdp'];

if(empty($pseudo))
  
die('Pseudo manquant!');
else
  
die(chr(149).chr(32).'Bonjour '.$pseudo.'!');
?>

Il est tout de même conseillé de vérifier la syntaxe des données avant de les utiliser pour contrer un éventuel piratage par injections SQL. Pour cela, vous pouvez utiliser la fonction Verifie_Syntax contenue dans le script func.php. Par exemple, le code suivant vérifie que le pseudo ne contient que des chiffres ou des lettres en minuscule :

$res=Verifie_Syntax($pseudo, $cst['nbr'].$cst['min']);
if(!empty($res))
  
die('Votre pseudo contient un caractère interdit ('.$res.').');
 

Réception des messages PHP avec DELPHI:
Pour différencier les messages d'erreurs et les messages de données, un caractère spécial (
149) suivi d'un espace (32) est placé au début des données. Ainsi, lorsque le programme Delphi réceptionne le résultat du script PHP, il teste les 2 premiers caractères pour déterminer si il s'agit d'un message d'erreur ou non :
- Les messages d'erreur seront placés dans la chaîne
StringError.
- Les messages de données, dans la chaîne
StringResult.
 

CONVERSIONS DES DONNEES AVEC DELPHI

Etant donné que les messages d'erreur de PHP sont au format HTML, j'ai réalisé une petite fonction Delphi nommée
StripHtmlTags pour supprimer les balises HTML et pouvoir afficher proprement les messages avec la fonction ShowMessage de Delphi. Cette fonction remplace également les balises <BR> par des sauts de ligne Windows (#13). Cela dit, dans le cas où vous souhaiteriez envoyer du code HTML vers votre programme Delphi, utilisez le mode binaire de la méthode StartPost pour conserver le format initial des données.

Vous disposez également de la fonction Delphi
StrExplode pour découper une chaîne de caractère en liste de chaîne. Cette fonction est prévue pour convertir le résultat PHP en tableau de chaîne et ainsi récupérer des tableaux PHP dans le programme Delphi.

La fonction Delphi
AddSlashes permet d'échapper les caractères spéciaux avant d'effectuer des requêtes SQL avec Delphi. Cette fonction est nécessaire si vous souhaitez enregistrer ou modifier du texte dans votre base de données. Noter que cette fonction pourrait aussi être effectuée avec PHP lors de la réception des données.
 

DELIMITATION DES DONNEES PHP

Durant les premiers tests du code, [Silk], un membre du forum, a eu l'occasion de l'installer sur un hébergement gratuit où une bannière de publicité est automatiquement ajoutée sur toutes les pages de l'hébergement. A cause de cela, les données réceptionnées avec Delphi étaient altérées car le programme réceptionnait aussi le code HTML de la bannière sans pouvoir faire de distinction.

Pour résoudre ce problème, il a fallu encadrer les données émises par les scripts PHP avec 2 chaînes de caractères spéciaux. La fonction
Mydie du script func.php s'occupe justement d'ajouter ces délimiteurs au début et à la fin de tous les messages PHP. De cette manière, lors de la réception des messages, Delphi supprime les données situées à l'extérieur des délimiteurs.
 

TIMEOUT & PROGRESSION AVEC DELPHI

Le composant THttpPost possède un TimeOut qui est réinitialisé chaque fois que le programme réceptionne des nouvelles données. Cela est différent du temps total d'exécution. Il s'agit plutôt d'un TimeOut d'inactivité.

La propriété
MaxTimeOut définit la valeur de ce TimeOut en millisecondes. Par défaut, sa valeur est fixée à 10000, soit 10 secondes. Selon le programme, il est probable qu'il faille augmenter ce délai pour des requêtes très longues à répondre. Il est conseillé d'utiliser la fonction flush de PHP pour demander au script d'émettre les données lorsque cela est possible.
 

SOURCES

Télécharger le code de l'exemple ci-dessus :
delphpunit.zip  
• Installer le script "connect.php" sur votre serveur
• Définir l'url de ce script dans la propriété URL de l'objet HttpPost1

Vous pouvez choisir d'utiliser la dernière version du composant d'ICS :
HttpCli6.zip
L'unité se nomme OverbyteIcsHttpProt au lieu de HttpProt...
 

Cliquer ici pour lire la suite de l'article...