Sunteți pe pagina 1din 29

PHP : l'extension cURL

par julp (Autres articles)

Date de publication : 12/06/2007

Dernière mise à jour :

La librairie cURL permet de communiquer facilement avec de nombreux types de serveurs


applicatifs en parlant le même langage que celui-ci. Ce langage est définit par ce qu'on
appelle un protocole dont les plus connus sont sans aucun doute HTTP et FTP. L'extension
cURL permet d'interagir en PHP avec tous ces protocoles que nous employons de manière
quotidienne sans avoir à gérer la connexion ou encore sans se soucier de la manière dont
il faut écrire la requête ou en recevoir la réponse.
PHP : l'extension cURL par julp (Autres articles)

1 - Installation.............................................................................................................................................................. 3
1.1 - Windows.........................................................................................................................................................3
1.2 - Unix/Linux...................................................................................................................................................... 3
1.2.1 - Statique..................................................................................................................................................3
1.2.2 - Dynamique.............................................................................................................................................3
2 - Vue d'ensemble......................................................................................................................................................5
2.1 - Les fonctions..................................................................................................................................................5
2.2 - Les options.................................................................................................................................................... 8
3 - Utilisation.............................................................................................................................................................. 11
3.1 - Le protocole HTTP...................................................................................................................................... 11
3.1.1 - Vérifier l'existence d'une URL............................................................................................................. 11
3.1.2 - Récupérer le contenu d'une page.......................................................................................................11
3.1.3 - Envoyer des données par la méthode POST..................................................................................... 12
3.1.4 - Débuter une session puis la réutiliser.................................................................................................14
3.1.5 - Source : simplifier l'utilisation de cURL pour le protocole HTTP.........................................................15
3.2 - Le protocole FTP......................................................................................................................................... 18
3.2.1 - Lister un répertoire distant.................................................................................................................. 18
3.2.2 - Envoyer un fichier............................................................................................................................... 19
3.2.3 - Télécharger un fichier......................................................................................................................... 20
3.3 - Le protocole LDAP...................................................................................................................................... 21
4 - Alternatives : mise en parallèle avec d'autres méthodes.................................................................................... 23
4.1 - Vérifier l'existence d'une page.....................................................................................................................23
4.2 - Récupérer le corps d'une page................................................................................................................... 24
4.3 - Recevoir un fichier par FTP........................................................................................................................ 26
4.4 - Envoyer un fichier par FTP......................................................................................................................... 27
5 - Conclusion............................................................................................................................................................29
5.1 - Epilogue....................................................................................................................................................... 29

-2-
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

1 - Installation

1.1 - Windows

Récupérez la version binaire zippée de PHP pour Windows. Placez ensuite php_curl.dll avec les autres
(généralement il s'agit du répertoire extensions pour PHP 4 et ext pour PHP 5). Indiquez à PHP de charger l'extension
en éditant le fichier php.ini pour y ajouter la ligne suivante :

extension=php_curl.dll

Vous aurez également besoin de copier les librairies libeay32.dll ainsi que ssleay32.dll dans un des répertoires
pointés par votre variable d'environnement PATH. Modifiez la au besoin ou alors utilisez directement C:\WINDOWS
\system32\.

Enfin, un redémarrage de votre serveur sera probablement nécessaire pour prendre en charge immédiatement cette
nouvelle extension.

1.2 - Unix/Linux

L'installation de PHP ou de l'extension à partir de ses sources s'adresse à des utilisateurs initiés pour répondre à
des besoins particuliers. Privilégiez autant que possible les paquets mis à disposition par le distributeur de votre
distribution Linux ou de votre système Unix auquel cas il ne devrait vous rester qu'à activer cette extension en éditant
le fichier php.ini (voir ci-dessous la partie intitulée "Dynamique"). Par exemple, dans le cas de Mandriva où vos médias
sont convenablement renseignés, l'installation se fera par cette commande : urpmi phpVERSION-curl (remplacez
VERSION par 4 ou 5 suivant la version de PHP utilisée).

1.2.1 - Statique

Les sources de cette extension étant distribuées avec celles de PHP nous devons simplement ajouter l'option --with-
curl lors du script configure :

./configure --prefix=/usr/local/php ... --with-curl


make
make install

1.2.2 - Dynamique

Cette méthode présente l'avantage de ne pas requérir une recompilation complète de PHP et d'être indépendante
(jusqu'à un certain point) du coeur de PHP. Voici comment procéder à la compilation :

cd /répertoire/des/sources/de/l/extension
phpize
./configure
make
make install

Vous devez ensuite modifier le fichier php.ini afin de disposer des fonctions cURL en chargeant l'extension à l'aide
de la ligne suivante :

-3-
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

extension=curl.so

Assurez-vous que les chemins indiqués par la directive extension_dir sont corrects puisque PHP sera alors incapable
de charger les extensions demandées auquel cas vous obtiendriez des messages d'erreur et aucune des fonctions
qu'elles sont censées fournir.

-4-
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

2 - Vue d'ensemble

2.1 - Les fonctions

Dans la plupart des cas, le recours à cURL en PHP se résume à quelques appels de fonctions dont l'ordre vous est
présenté par le schéma ci-dessous :

Voyons maintenant le rôle que joue chacune de ces fonctions ainsi que leurs prototypes :

• ressource curl_init([chaîne url]) :

Initialise une nouvelle session cURL. Son seul paramètre url peut être omis mais il ne faudra pas oublier de
l'indiquer par la suite avec la fonction curl_setopt, option CURLOPT_URL. Cette fonction renverra une ressource
exploitable par les autres fonctions curl ou FALSE en cas d'erreur.
• booléen curl_setopt(ressource curl, entier option, variable valeur) :

Définit le comportement de la session. Elle renvoie TRUE en cas de succès et FALSE si une erreur est
rencontrée. Ces paramètres sont les suivants :

• curl : la session cURL (résultat de l'appel à curl_init)


• option : le nom de l'option sous la forme d'une constante, celles-ci commencent par CURLOPT_* et les
principales seront présentées plus bas
• valeur : la valeur à donner, son type (numérique, booléen, etc) est variable et est propre à l'option
utilisée

• variable curl_exec(ressource curl) :

Exécute la session cURL représentée par curl (résultat de la fonction curl_init). Toutes les informations
nécessaires doivent être fournies au préalable avec la fonction curl_setopt. Elle retourne FALSE si une erreur
survient et dans le cas contraire une valeur qui dépend de la valeur de l'option CURLOPT_RETURNTRANSFER.
En effet, si cette option est fixée à FALSE (valeur par défaut), curl_exec renvoie alors TRUE sinon le résultat
de la requête (du texte).
• rien curl_close(ressource curl) :

-5-
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

Met fin à la session cURL désignée par le paramètre curl (résultat de la fonction curl_init) et libère les ressources
allouées.

Fonctions supplémentaires utiles :

• chaîne curl_error(ressource curl) :

Permet d'obtenir le texte décrivant la dernière erreur produite. S'il n'y en a pas eu, vous récupérerez alors une
chaîne vide. Notez que cette fonction attend la session cURL courante issue de la fonction curl_init, elle doit
donc par conséquent être appelée avant curl_close.
• variable curl_getinfo(ressource curl [, entier option]) :

Fournit diverses informations concernant la dernière session indiquée par le paramètre curl. Si l'argument option
est fourni alors seule l'information correspondante sera retournée et s'il est omis vous les obtiendrez toutes
sous la forme d'un tableau associatif.

Le paramètre option peut prendre l'une des valeurs suivantes sous les traits d'une constante :

-6-
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

Nom Description
CURLINFO_EFFECTIVE_URL
Dernière URL effective utilisée.
CURLINFO_HTTP_CODE
Code HTTP de la dernière réponse reçue. La valeur sera
nulle si aucune réponse n'a (encore) été reçue.
CURLINFO_FILETIME
Timestamp indiquant la date du fichier distant. La valeur -1
sera renvoyée si cette information n'est pas disponible et ce
quelqu'en soit la raison.
CURLINFO_TOTAL_TIME
Durée totale exprimée en secondes du précédent transfert
(ceci inclue toutes les étapes de la connexion comme la
résolution d'adresse).
CURLINFO_NAMELOOKUP_TIME
Temps (en secondes) mis depuis le début (de la fonction
curl_exec) jusqu'à la résolution de nom.
CURLINFO_CONNECT_TIME
Temps mis en secondes depuis le début à l'établissement de
la connexion avec l'hôte distant ou le proxy.
CURLINFO_PRETRANSFER_TIME
Délai (en secondes) séparant le début au début du transfert.
Cette étape inclue l'envoi des pré-commandes comme le
permet l'option CURLOPT_QUOTE, par exemple.
CURLINFO_STARTTRANSFER_TIME
Temps, en secondes, écoulé entre le début et l'envoi du
premier octet du transfert.
CURLINFO_REDIRECT_TIME
Durée totale du transfert incluant les différentes redirections.
La valeur sera nulle si la requête n'a fait l'objet d'aucune
redirection.
CURLINFO_REDIRECT_COUNT
Nombre de redirections suivies.
CURLINFO_SIZE_UPLOAD
Nombre d'octets envoyés.
CURLINFO_SIZE_DOWNLOAD
Nombre d'octets reçus pour le dernier transfert.
CURLINFO_SPEED_DOWNLOAD
Vitesse de téléchargement moyenne mesurée en octets/
seconde.
CURLINFO_SPEED_UPLOAD
Vitesse d'envoi moyenne exprimée en octets/seconde.
CURLINFO_HEADER_SIZE
En octets, taille totale de tous les en-têtes reçus.
CURLINFO_REQUEST_SIZE
Taille totale des requêtes effectuées (inclue les pages de
redirection si CURLOPT_FOLLOWLOCATION est à TRUE).
Cette information ne concerne que le protocole HTTP.
CURLINFO_SSL_VERIFYRESULT
Résultat de la vérification de la certification demandée via
l'option CURLOPT_SSL_VERIFYPEER.
CURLINFO_CONTENT_LENGTH_DOWNLOAD
Valeur lue et correspondant au champ Content-Length dans
la réponse.
CURLINFO_CONTENT_LENGTH_UPLOAD
Taille spécifiée pour l'envoi (c'est à dire à la valeur de l'option
CURLOPT_INFILESIZE).
CURLINFO_CONTENT_TYPE
La valeur de l'en-tête Content-Type telle qu'elle a été lue.
Vous pouvez obtenir la valeur NULL si le protocole ne
gère pas cette en-tête ou si le serveur en a envoyé une qui
s'avère être invalide.

En revanche si vous n'utilisez pas ce deuxième paramètre, voilà la forme que prendra le tableau ainsi renvoyé
par la fonction curl_getinfo :

Array
( // Voir ci-dessus la description de la constante :
'url' => 'http://www.developpez.com/', // CURLINFO_EFFECTIVE_URL
'content_type' => 'text/html', // CURLINFO_CONTENT_TYPE
'http_code' => 200, // CURLINFO_HTTP_CODE
'header_size' => 145, // CURLINFO_HEADER_SIZE
'request_size' => 58, // CURLINFO_REQUEST_SIZE

-7-
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

'filetime' => -1, // CURLINFO_FILETIME


'ssl_verify_result' => 0, // CURLINFO_SSL_VERIFYRESULT
'redirect_count' => 0, // CURLINFO_REDIRECT_COUNT
'total_time' => 0.125, // CURLINFO_TOTAL_TIME
'namelookup_time' => 0, // CURLINFO_NAMELOOKUP_TIME
'connect_time' => 0.052, // CURLINFO_CONNECT_TIME
'pretransfer_time' => 0.052, // CURLINFO_PRETRANSFER_TIME
'size_upload' => 0, // CURLINFO_SIZE_UPLOAD
'size_download' => 0, // CURLINFO_SPEED_DOWNLOAD
'speed_download' => 0, // CURLINFO_SPEED_DOWNLOAD
'speed_upload' => 0, // CURLINFO_SPEED_UPLOAD
'download_content_length' => 0, // CURLINFO_CONTENT_LENGTH_DOWNLOAD
'upload_content_length' => 0, // CURLINFO_CONTENT_LENGTH_UPLOAD
'starttransfer_time' => 0.124, // CURLINFO_STARTTRANSFER_TIME
'redirect_time' => 0 // CURLINFO_REDIRECT_TIME
)

2.2 - Les options

La liste des options que nous allons voir est loin d'être exhaustive : nous n'aborderons en effet que les principales
options de l'extension suivant leur rôle et en prenant en compte le ou les protocoles avec lesquels elles peuvent
être employées.

Passons en revue tout d'abord les paramètres généraux de la connexion qui sera établie par cURL :

Nom Description
CURLOPT_URL URL à utiliser pour établir la connexion (alternative au paramètre url
de la fonction curl_init). La forme de celle-ci dépend du protocole
employé.
CURLOPT_TIMEOUT Temps maximal d'exécution, exprimé en secondes, de la fonction
curl_exec.
CURLOPT_CONNECTTIMEOUT
Durée maximale de la tentative d'établissement de la connexion
vers l'hôte distant (en secondes). Une valeur nulle aura pour effet
de laisser cette tâche au système.

Voyons en maintenant d'autres toutes aussi générales qui, elles, sont liées au transfert des données :

Nom Description
CURLOPT_NOBODY Fixée à TRUE la partie "contenu" ne sera pas renvoyée. Par
exemple avec le protocole HTTP, la requête employée sera de type
HEAD au lieu de GET par défaut. Sa valeur par défaut est FALSE,
rapatriant ainsi les données distantes.
CURLOPT_HEADER Suivant le protocole employé, la valeur TRUE permettra d'inclure
les en-têtes dans le résultat renvoyé. La valeur par défaut est
FALSE.
Avec la valeur TRUE, le contenu de la page distante est retourné
CURLOPT_RETURNTRANSFER
sous la forme d'une chaîne par la fonction curl_exec. La valeur par
défaut FALSE a pour effet d'en afficher directement la sortie.
CURLOPT_FILE Un descripteur de fichier (préalablement obtenu et ouvert avec
fopen en mode écriture) dans lequel sera alors écrit les données
renvoyées par le serveur distant. La valeur par défaut est la sortie
standard soit le navigateur dans une utilisation "web" de PHP.
CURLOPT_UPLOAD Permet d'indiquer, en attribuant la valeur TRUE à cette option, à
cURL qu'un envoi de fichier va avoir lieu et qu'il doit s'y préparer.
CURLOPT_INFILE Un descripteur de fichier, auparavant obtenu et ouvert en lecture
par la fonction fopen, duquel les données pour l'upload seront lues.
CURLOPT_INFILESIZETaille du fichier qui sera envoyé au serveur distant.

-8-
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

Abordons à présent les particularités du protocole HTTP :

Nom Description
CURLOPT_HTTP_VERSION
Forcer la version du protocole HTTP utilisée. La valeur par défaut
est CURL_HTTP_VERSION_NONE, laissant ainsi le soin à cURL
de décider sinon forcez la à l'aide de CURL_HTTP_VERSION_1_0
ou CURL_HTTP_VERSION_1_1 qui correspondent respectivement
aux versions 1.0 et 1.1.
TRUE pour suivre (toutes) les redirections de type "Location:".
CURLOPT_FOLLOWLOCATION
On peut toutefois limiter le nombre de celles-ci avec l'option
CURLOPT_MAXREDIRS.
CURLOPT_MAXREDIRS
Spécifie le nombre maximum de redirections qui seront suivies
avant de faire échouer la requête. Une valeur nulle implique aucune
redirection alors que -1 (valeur par défaut) signifie toutes.
CURLOPT_HTTPGET La méthode HTTP employée sera GET. Il s'agit du type de requête
par défaut.
CURLOPT_POST Définir cette option à la valeur TRUE aura pour effet d'employer la
méthode POST à la place de la méthode GET par défaut.
CURLOPT_POSTFIELDS
Les données à envoyer par la méthode POST sous la forme d'une
chaîne (doivent être encodées) ou d'un tableau associant le nom
du champ à sa valeur. Cette deuxième forme ne nécessite pas
l'encodage des données car elle sera réalisée en interne et permet
d'envoyer des fichiers en faisant précéder leur nom d'une arobase.
CURLOPT_USERPWDPermet de fournir un identifiant et un mot de passe pour passer
les systèmes d'authentification HTTP. Ils prennent alors la forme
login:mot_de_passe.
CURLOPT_USERAGENT
Définit l'en-tête User-Agent (le navigateur) pour la requête HTTP.
CURLOPT_REFERERRenseigne l'en-tête Referer, la page d'où on provient en temps
normal.
Avec la valeur TRUE cURL renseignera automatiquement l'en-tête
CURLOPT_AUTOREFERER
Referer lors de redirections.
CURLOPT_HTTPHEADER
Ensemble d'en-têtes à présenter lors de la requête sous la forme
d'un tableau numériquement indexé.
CURLOPT_COOKIEFILE
Indique le fichier duquel seront lues les données relatives aux
cookies.
CURLOPT_COOKIEJAR
Fichier où seront écrites les données des différents cookies reçus.

Et enfin la gestion du protocole FTP :

Nom Description
CURLOPT_QUOTE Un tableau numériquement indexé des commandes FTP à exécuter
avant notre requête.
CURLOPT_POSTQUOTE
Les commandes FTP à exécuter après notre requête sous la forme
d'un tableau numériquement indexé.
CURLOPT_TRANSFERTEXT
Une valeur vraie indique à cURL d'utiliser le mode de transfert
appelé ASCII au lieu du mode binaire par défaut. Toutefois,
attention : le mode ascii est implémenté de manière incomplète au
sein de cURL.
CURLOPT_FTP_SSL Permet de spécifier, à l'aide d'une des constantes ci-dessous, le
niveau de sécurité des données qui vont transiter :

• CURLFTPSSL_NONE : connexion FTP normale, aucun


recours à SSL

-9-
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)


CURLFTPSSL_TRY : tente d'utiliser SSL ou à défaut le
protocole normal
• CURLFTPSSL_CONTROL : SSL sera requis sur la connexion
de contrôle sinon cURL échouera
• CURLFTPSSL_ALL : SSL sera requis à la fois pour la
connexion de contrôle ainsi que sur le canal de données
CURLOPT_FTPSSLAUTH
Détermine l'ordre des versions du protocole SSL à employer :

• CURLFTPAUTH_DEFAULT : laisse à cURL le soin de décider


• CURLFTPAUTH_SSL : tente d'utiliser SSL avant TLS
• CURLFTPAUTH_TLS : tente d'utiliser TLS avant SSL

- 10 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

3 - Utilisation

3.1 - Le protocole HTTP

3.1.1 - Vérifier l'existence d'une URL

Le but du jeu consiste à envoyer une requête de type HEAD vers la page indiquée est d'en obtenir le code HTTP
correspondant. Bien sûr s'il n'y a aucun serveur HTTP à l'adresse et port indiqués, la fonction curl_exec échouera.

Les codes considérés comme synonymes de succès sont :

• 200 (OK) : la requête aboutie normalement


• 301 (Moved Permanently) : la ressource visée a été définitivement déplacée, cette URL est obsolète
• 302 (Temporary Redirect) : la page est temporairement accessible via une autre URL

Nous utiliserons donc les options de timeout (CURLOPT_TIMEOUT et CURLOPT_CONNECTTIMEOUT) pour


assurer que le script nous rende, quoiqu'il arrive, rapidement la main ainsi que CURLOPT_NOBODY car le contenu de
la page ne nous intéresse pas ici. Nous obtiendrons uniquement ce code d'erreur en combinant la fonction curl_getinfo
à sa constante CURLINFO_HTTP_CODE que nous comparerons ensuite aux valeurs données ci-dessus :

function http_check_url($url, $timeout = 10)


{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_NOBODY, TRUE);
if (strpos($url, 'https://') === 0) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // On ne vérifie que l'existence de la page
}
if (!curl_exec($ch)) {
return FALSE;
}
$ret = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

return in_array($ret, array(200, 301, 302));


}

// Exemple d'utilisation :
define('OK', '<span style="color: green">OK</span>');
define('KO', '<span style="color: red">KO</span>');
$urls = array(
'http://www.non-existant.fr',
'http://www.developpez.com/',
'http://php.developpez.com/faq/'
);
foreach ($urls as $u) {
echo $u . ' : ' . (http_check_url($u) ? OK : KO) . '<br/>';
}

3.1.2 - Récupérer le contenu d'une page

Nous sommes parfois amenés à vouloir récupérer le contenu d'une page distante sous la forme d'une chaîne de
caractères à des fins toutes aussi diverses comme par exemple pour en extraire certaines informations, constituer
un cache, etc. Cette pratique est monnaie courante avec le protocole HTTP mais puisque nous utilisons cURL est
aussi valable pour d'autres, citons par exemple FTP.

- 11 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

L'option cURL la plus importante ici est CURLOPT_RETURNTRANSFER. En effet, si celle-ci est omise ou n'est pas
fixée à une valeur vraie, le contenu du fichier distant sera directement renvoyé au navigateur de votre visiteur or nous
souhaitons le traiter. Nous réutiliserons des options que nous avons déjà vues auparavant, notamment celles liées à
la durée maximale d'exécution de la requête par cURL. Voyons comment implémenter une telle fonction :

function http_fetch_url($url, $timeout = 10, $userpwd = '')


{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if ($userpwd) {
curl_setopt($ch, CURLOPT_USERPWD, $userpwd);
}
$data = curl_exec($ch);
curl_close($ch);

return $data;
}

// Exemple d'utilisation :
if (($content = http_fetch_url('http://www.monsite.fr/zone_privee/sqldump.php',
10, 'utilisateur:mot_de_passe')) === FALSE) {
die("Une erreur est survenue");
} else {
echo htmlentities($content);
}

Les paramètres d'identification (login et mot de passe) peuvent directement figurer dans l'URL comme ils peuvent
être spécifiés à part via l'option CURLOPT_USERPWD, introduite ci-dessus à titre informatif.

Pour des raisons légales, vous êtes fortement invités à prendre préalablement contact
avec les responsables des sites sur lesquels vous voudriez reprendre des informations.

3.1.3 - Envoyer des données par la méthode POST

Pour utiliser la méthode POST, nous permettant ainsi d'envoyer des données conséquentes et de simuler la
soumission d'un formulaire, l'une des méthodes consiste à regrouper l'ensemble de ces données sous la forme d'une
chaîne encodée qui sera ensuite fournie à la session cURL via l'option CURLOPT_POSTFIELDS. Parfaitement,
les informations à transmettre doivent être encodées conformément à la définition du protocole HTTP pour
garantir la syntaxe de la requête, rappelons que les données doivent se présenter sous la forme suivante :
param1=valeur1&param2=valeur2&...&paramN=valeurN et qu'un certain nombre de caractères spéciaux vis-à-vis du
protocole HTTP doivent être encodés. En PHP 5, la fonction http_build_query permet de gérer directement tous ces
aspects, en revanche, pour PHP 4 il nous faudra la réécrire (voir ci-dessous).

Voyons un exemple sans réel intérêt, dont le rôle est de retransmettre les données POST reçues par un script à
destination d'une autre page :

// Pour assurer la compatibilité avec les versions PHP 4


if (!function_exists('http_build_query')) {

function http_build_query($formdata, $numeric_prefix = NULL, $arg_separator = '', $parent_key = '') {


$ret = array();
if (is_array($formdata)) {
if (empty($arg_separator)) {
$arg_separator = ini_get('arg_separator.output');
}
foreach ($formdata as $k => $v) {
if (is_int($k) && $numeric_prefix != NULL) {

- 12 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

$k = $numeric_prefix . $k;
}
if ($parent_key != '') {
$k = sprintf('%s[%s]', $parent_key, $k);
}
if (is_array($v)) {
array_push($ret, http_build_query($v, NULL, $arg_separator, $k));
} elseif (is_object($v)) {
array_push($ret, http_build_query(get_object_vars($v), NULL, $arg_separator, $k));
} else {
array_push($ret, urlencode($k) . '=' . urlencode($v));
}
}
}
return implode($arg_separator, $ret);
}
}

// Faire suivre les données POST à une autre page


$ch = curl_init('http://www.monsite.fr/formulaire.html');
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($_POST));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$ret = curl_exec($ch);
if (!$ret) {
echo curl_error($ch);
} else {
echo $ret;
}
curl_close($ch);

L'autre méthode simplifiant quelque peu les choses est de donner à cette option non pas une chaîne de caractères
mais un tableau associant le nom du paramètre à sa valeur. L'intérêt est double :

• Vous n'avez pas à vous soucier de la forme des données : elles seront regroupées et encodées en interne
par cURL
• Cela permet l'upload de fichiers : tout paramètre dont le nom commence par une arobase et correspondant à
un fichier local sera joint

Voyons un exemple visant à simuler la validation d'un formulaire comportant un champ de type textarea (nommé
description) et un de type file (photo) :

// Données à envoyer
$post = array(
// La zone de texte "description"
'description' => "Photo n°1 de mon week-end en Bretagne.\r
\nPique-nique dans la forêt de Broceliande.",
// Le fichier à uploader sous "photo"
'photo' => '@' . realpath('P1010001.JPG')
);

// On effectue la requête avec cURL


$ch = curl_init('http://www.monsite.fr/envoi_photo.php');
curl_setopt($ch, CURLOPT_NOBODY, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$ret = curl_exec($ch);
if (!$ret) {
echo curl_error($ch);
} else {
echo 'Envoi OK !';
}
curl_close($ch);

- 13 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

3.1.4 - Débuter une session puis la réutiliser

Certaines pages requièrent parfois une authentification avant de donner accès à un contenu plus vaste. Il est alors
nécessaire d'établir une première connexion pour créer une session côté serveur afin de mémoriser cette identification
et de pouvoir lire par la suite l'ensemble des données du site. Pour cela nous devons faire parvenir son identifiant
au serveur pour ne plus avoir à repasser par la case authentification (sur un temps limité) et consulter directement
les pages qui nous intéressent par la suite.

Un serveur employant PHP (versions 4 et supérieures) propose deux méthodes indépendantes et complémentaires
pour faire transiter l'identifiant de session à savoir : l'utilisation d'un cookie de session ou la réécriture des liens
internes et formulaires de sorte à le transmettre à la prochaine requête.

Pour correspondre à un maximum de configuration nous utiliserons les options proposées par cURL pour recourir
aux cookies et nous parserons le corps de la page à la recherche d'un tel identifiant. La première étape consiste
donc à s'authentifier pour initialiser une session "valide" et de tenter de capturer cet identifiant de session, suivant la
configuration du serveur distant, pour pouvoir ensuite le réexploiter lors de notre deuxième requête.

Lors de la deuxième, nous renverrons cet identifiant, si nous l'avons trouvé, en méthode GET (la méthode POST le
permet aussi), ce qui devrait nous donner directement accès au document que nous souhaitons consulter.

Voici une méthode de procéder propre à un serveur PHP :

define('LOGIN', 'julp');
define('PASSWORD', 'mdp');
define('AUTHENTIFICATION', 'http://localhost/curl/session/login.php');
define('PAGE_PRIVEE', 'http://localhost/curl/session/admin.php');

$sid = '';

/**
* Première connexion : authentification
**/
$ch = curl_init(AUTHENTIFICATION);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS,
array(
'login' => LOGIN,
'mdp' => PASSWORD
)
);
curl_setopt($ch, CURLOPT_COOKIEJAR, realpath('cookie.txt'));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_COOKIESESSION, TRUE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$ret = curl_exec($ch);
if ($ret === FALSE) {
die(curl_error());
}
curl_close($ch);
if (preg_match('/(PHPSESSID=[0-9a-z,-]{32,40})/i', $ret, $m)) {
$sid = '?' . $m[1];
} else if (preg_match('#<input\s+type="hidden"\s+name="([^\r\n\t <>\'"\\
\]+)"\s+value="([0-9a-z,-]{32,40})"\s*/?>#i', $ret, $m)) {
$sid = '?' . $m[1] . '=' . $m[2];
}

/**
* Deuxième partie : réutilisation de la session sur une page tierce
**/
$ch = curl_init(PAGE_PRIVEE . $sid);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_COOKIEFILE, realpath('cookie.txt'));

- 14 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

$ret = curl_exec($ch);
if ($ret === FALSE) {
die(curl_error());
}
curl_close($ch);
echo $ret;

Pour rappel : cURL n'interprète pas les langages (HTML ou Javascript notamment) ainsi il peut être mis à mal par
des redirections à effectuer côté client (balise meta, window.location.href). Ce problème ne se pose pas lorsqu'elles
sont effectuées côté serveur grâce à l'en-tête "Location:".

Pour en savoir plus sur les sessions php (utilisation comme configuration), je vous invite
à consulter l'article éponyme : Les sessions en PHP.

3.1.5 - Source : simplifier l'utilisation de cURL pour le protocole HTTP

Voici une classe PHP 5 qui vous permet d'interroger facilement et rapidement des serveurs HTTP :

class HTTPQuery
{
/**
* Tableau : les données POST qui seront envoyées (nom du champ => valeur)
**/
protected $_post;

/**
* Tableau des options cURL définies par l'utilisateur (option => valeur)
**/
protected $_options;

/**
* La ressource cURL
**/
protected $_ch;

/**
* Constructeur
* @param url URL à laquelle la requête sera envoyée
* @throws Exception si l'extension cURL n'est pas active
**/
public function __construct($url)
{
if (!extension_loaded('curl')) {
throw new Exception("L'extension curl n'est pas disponible");
}
$this->_ch = curl_init($url);
$this->_options = array();
}

/**
* Obtenir la valeur des options cURL avec la syntaxe $ojet->CURLOPT_X définie par l'utilisateur
* @param nom le nom de l'option cURL
* @return NULL si l'option n'a pas été définie sinon sa valeur
**/
public function __get($nom)
{
$resultat = NULL;
if (defined($nom)) {
$valeur = constant($nom);
if (isset($this->_options[$valeur])) {
$resultat = $this->_options[$valeur];
}
}
return $resultat;

- 15 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

/**
* Fixer les valeurs des options cURL avec la syntaxe $objet->CURLOPT_X = Y
* @param nom le nom de l'option cURL (constantes CURLOPT_*)
* @param valeur la nouvelle valeur de l'option (écrase la précédente)
* @throws Exception si l'option "nom" n'est pas valide (inexistante ou ne commençant pas par CURLOPT_) ou est
* protégée de façon à ce que vous passiez par les méthodes déléguées à la fonctionnalité ci
**/
public function __set($nom, $valeur)
{
if (defined($nom) && preg_match('/^CURLOPT_(?!POSTFIELDS)/', $nom)) {
$this->_options[constant($nom)] = $valeur;
} else {
throw new Exception("Option '$nom' invalide ou protégée");
}
}

/**
* Prendre connaissance de la définition d'une option cURL par l'utilisateur
* @param nom le nom de l'option cURL
* @return un booléen indiquant si cette option a été définie
**/
public function __isset($nom)
{
return (defined($nom) && isset($this->_options[constant($nom)]));
}

/**
* Détruire la définition d'une option cURL
* @param nom le nom de l'option cURL à détruire
**/
public function __unset($nom)
{
if (defined($nom) && isset($this->_options[constant($nom)])) {
unset($this->_options[constant($nom)]);
}
}

/**
* Description de l'objet
* @return une chaîne de caractères décrivant l'objet
**/
public function __toString()
{
return sprintf("%s (%s)", __CLASS__, curl_getinfo($this->_ch, CURLINFO_EFFECTIVE_URL));
}

/**
* Fixer la durée maximale d'exécution de la requête
* @param timeout cette durée exprimée en secondes
**/
public function setTimeout($timeout)
{
$timeout = intval($timeout);
if ($timeout > 0) {
$this->CURLOPT_TIMEOUT = $timeout;
$this->CURLOPT_CONNECTTIMEOUT = $timeout;
}
}

/**
* Ajouter des données textuelles aux données POST à envoyer
* @param nom_champ le nom du champ (permet d'exploiter les données côté serveur - $_POST)
* @param valeur les données correspondantes à envoyer
* @return un booléen indiquant que les données ont été prises en compte
**/
public function addPostData($nom_champ, $valeur)
{
if (!isset($this->_post[$nom_champ]) && !is_array($valeur)) {
$this->_post[$nom_champ] = $valeur;
return TRUE;

- 16 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

} else {
return FALSE;
}
}

/**
* Ajouter un fichier aux données POST à envoyer (upload de fichiers)
* @param nom_champ le nom du champ (permet d'exploiter le fichier à sa réception - $_FILES)
* @param fichier le fichier à envoyer
* @throws Exception si le fichier indiqué est inexistant ou n'est pas un fichier régulier
**/
public function addPostFile($nom_champ, $fichier)
{
if (is_file($fichier)) {
$this->_post[$nom_champ] = '@' . realpath($fichier);
} else {
throw new Exception("Le fichier '$fichier' n'existe pas ou n'est pas un fichier régulier");
}
}

/**
* Exécuter la requête
* @param fichier_sortie, renseigné le contenu de la page distante est écrit dans le fichier indiqué
* @return le contenu de la page distante ou alors TRUE si le paramètre fichier_sortie a été utilisé
* @throws Exception en cas d'erreur liée à cURL ou à l'écriture du fichier
**/
public function doRequest($fichier_sortie = FALSE)
{
if ($this->_options) {
if (function_exists('curl_setopt_array')) {
curl_setopt_array($this->_ch, $this->_options);
} else {
foreach ($this->_options as $option => $valeur) {
curl_setopt($this->_ch, $option, $valeur);
}
}
}
if ($fichier_sortie) {
@ $fp = fopen($fichier_sortie, 'w');
if (!$fp) {
throw new Exception("Impossible d'ouvrir en écriture le fichier '$fichier_sortie'");
}
curl_setopt($this->_ch, CURLOPT_FILE, $fp);
} else {
curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, TRUE);
}
if ($this->_post) {
curl_setopt($this->_ch, CURLOPT_POST, TRUE);
curl_setopt($this->_ch, CURLOPT_POSTFIELDS, $this->_post);
}
$ret = curl_exec($this->_ch);
if ($fichier_sortie) {
fclose($fp);
}
if ($ret === FALSE) {
throw new Exception("Une erreur est survenue : '" . curl_error($this->_ch) . "'");
}
return $ret;
}

/**
* Destructeur
**/
public function __destruct()
{
unset($this->_options);
unset($this->_post);
curl_close($this->_ch);
}
}

- 17 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

Un exemple complet visant à afficher la sortie résultant de la soumission d'un formulaire distant d'upload de photos
comprenant d'autres champs plus classiques, le tout avec une authentification HTTP et utilisant le protocole HTTPS
pour la sécurité :

require_once('/var/www/offline/librairies/HTTPQuery.php');

try {
$http = new HTTPQuery('https://julp:mdp@mon_serveur/admin/ajouter_photo.php');
/* Quelques fichiers à uploader */
$http->addPostFile('images[0]', '../images1.jpg');
// Récupérée sur le serveur distant via $_FILES['images']['name'][0]
$http->addPostFile('images[1]', '../images2.jpg');
// Récupérée sur le serveur distant via $_FILES['images']['name'][1]
/* Les données correspondant aux différents champs du formulaire */
$http->addPostData('visibilite[0]', 'visiteurs'); // $_POST['visibilite']
[0] : simulation d'une checkbox
$http->addPostData('visibilite[1]', 'enregistrés'); // $_POST['visibilite']
[1] : simulation d'une checkbox
$http->addPostData('description', "Les photos de ce week-end.\r
\nC'est fou ce qu'il faisait beau."); // $_POST['description'] : simulation d'une textarea
$http->addPostData('submit', 'x'); // $_POST['submit'] : le bouton submit
/* Vérification du certificat présenté par le serveur */
$http->CURLOPT_CAINFO = 'ca-root.crt'; // Obtenu sur http://www.freebsd.org/cgi/
cvsweb.cgi/ports/security/ca-roots/files/
$http->CURLOPT_SSL_VERIFYPEER = TRUE;
/* On effectue enfin la requête */
echo $http->doRequest();
} catch (Exception $e) {
die($e->getMessage());
}

3.2 - Le protocole FTP

3.2.1 - Lister un répertoire distant

Il est possible d'obtenir la liste des fichiers présents dans un répertoire distant en utilisant le protocole FTP et l'option
CURLOPT_FTPLISTONLY. Le résultat est une liste des noms des fichiers (et aucune autre information comme leur
poids) séparés par des nouvelles lignes. Par conséquent voici une méthode pour exploiter et réutiliser ce résultat :

function curl_ftp_list($url, $timeout = 10)


{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_FTPLISTONLY, TRUE);
$ret = curl_exec($ch);
curl_close($ch);
if ($ret === FALSE) {
return FALSE;
} else {
return preg_split('/[\r\n]+/', $ret, -1, PREG_SPLIT_NO_EMPTY);
}
}

// Exemple d'utilisation :
$fichiers = curl_ftp_list('ftp://login:mot_de_passe@serveur/');
natsort($fichiers);
if ($fichiers === FALSE) {
die("La connexion n'a pu être établie");
} else {
echo '<ul>';

- 18 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

foreach ($fichiers as $f) {


if ($f != '.' and $f != '..') {
echo '<li>' . $f . '</li>';
}
}
echo '</ul>';
}

On peut cependant aller plus loin en envoyant la commande FTP LIST (via l'option CURLOPT_CUSTOMREQUEST)
qui nous permettra de récupérer en plus des noms des fichiers, leurs permissions, propriétaire, taille, etc. Toutefois,
ces informations étant renvoyées sous forme de texte monolithique il va nous falloir utiliser une expression régulière
afin de séparer ces différentes informations :

function curl_ftp_list_bis($url, $timeout = 10)


{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "LIST");
$ret = curl_exec($ch);
echo curl_error($ch);
curl_close($ch);
if ($ret === FALSE) {
return FALSE;
} else {
$fichiers = array();
$nbFichiers = 0;
if (preg_match_all('/([-dl])([rwxst-]{9})[ ]+([0-9]+)[ ]+([^ ]+)[ ]+(.+)[ ]+([0-9]+)[ ]+([a-zA-
Z]+[ ]+[0-9]+)[ ]+([0-9:]+)[ ]+(.*)/', $ret, $m, PREG_SET_ORDER)) {
foreach ($m as $f) {
$fichiers[$nbFichiers] = array();
$fichiers[$nbFichiers]['dir'] = $f[1] == 'd'; // Répertoire ?
$fichiers[$nbFichiers]['filename'] = $f[9]; // Nom
$fichiers[$nbFichiers]['size'] = $f[6]; // Taille
$fichiers[$nbFichiers]['owner'] = $f[4]; // Propriétaire
$fichiers[$nbFichiers]['group'] = $f[5]; // Groupe
$fichiers[$nbFichiers]['permissions'] = $f[2]; // Permissions
$fichiers[$nbFichiers]['mtime'] = "$f[7] $f[8]"; // Date de dernière modification
$nbFichiers++;
}
}
return $fichiers;
}
}

3.2.2 - Envoyer un fichier

Le fichier à envoyer doit tout d'abord être ouvert en écriture avec la fonction fopen (mode r). Ce descripteur de fichier
ainsi obtenu sera transmis à cURL par l'option CURLOPT_INFILE. Nous devons également indiquer la partie du
fichier concernée via CURLOPT_INFILESIZE mais notre but étant de faire parvenir ce fichier dans son intégralité
nous lui fournirons donc la taille réelle de celui-ci grâce à la fonction filesize. Enfin, nous signalons à cURL qu'il s'agit
d'un upload et qu'il doit s'y préparer en positionnant l'option CURLOPT_UPLOAD à vrai :

function curl_ftp_put($url, $nom_local, $mode_ascii = FALSE, $chmod = FALSE)


{
$ret = FALSE;

if (is_file($nom_local)) {
$fp = fopen($nom_local, 'r');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_INFILE, $fp);

- 19 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

curl_setopt($ch, CURLOPT_INFILESIZE, filesize($nom_local));


curl_setopt($ch, CURLOPT_UPLOAD, TRUE);
if ($mode_ascii) {
curl_setopt($ch, CURLOPT_TRANSFERTEXT, TRUE);
}
if ($chmod) {
$path = parse_url($url, PHP_URL_PATH);
curl_setopt($ch, CURLOPT_POSTQUOTE, array("SITE CHMOD $chmod $path"));
}
$ret = curl_exec($ch);
curl_close($ch);
fclose($fp);
}

return $ret;
}

// Exemple d'utilisation :
if (!curl_ftp_put('ftp://login:mot_de_passe@serveur/
mon_fichier.txt', 'mon_fichier.txt', TRUE, '0400')) {
die("Le fichier n'a pu être uploadé sur le serveur");
}

L'URL désigne bien le fichier à créer ou écraser et non le répertoire parent.


Veillez, de préférence, à fermer le fichier ouvert (fonction fclose) à la fin de l'envoi.

J'ai introduit dans l'exemple ci-dessus deux options que vous serez peut être amenés à réutiliser. Tout d'abord,
CURLOPT_TRANSFERTEXT qui indique que le mode de transfert à utiliser n'est pas le mode binaire (par défaut)
mais le mode ascii. Le protocole FTP propose en effet deux modes qui dépendent de la nature des données à envoyer
et qui lorsque le mode adéquat n'est pas employé donne souvent lieu à des corruptions de fichiers. La deuxième,
CURLOPT_POSTQUOTE, permet d'exécuter après la requête une liste (sous forme de tableau) de commandes qui
ici peut être employée pour fixer les permissions du fichier à l'issue de sa réception.

3.2.3 - Télécharger un fichier

Sur le même principe que l'envoi, il faut en premier lieu ouvrir le fichier local qui va accueillir les données reçues en
écriture. Chose que nous ferons avec la fonction fopen (mode w) et nous procurerons ensuite le descripteur de fichier
ainsi obtenu à cURL par l'intermédiaire de l'option CURLOPT_FILE :

function ftp_curl_get($url, $sortie, $timeout = 10)


{
if ($fp = fopen($sortie, 'w')) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$ret = curl_exec($ch);
curl_close($ch);
fclose($fp);
return $ret;
}
return FALSE;
}

// Exemple d'utilisation :
if (!ftp_curl_get('ftp://utilisateur:mot_de_passe@serveur/fichier_distant', 'nom_local')) {
die("Le fichier indiqué n'a pu être récupéré");
}

- 20 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

3.3 - Le protocole LDAP

cURL est également capable d'interroger un annuaire LDAP, le seul changement à apporter se situe alors au
niveau de l'URL dont la forme vous est rappelée ci-dessous. Cependant, il faut savoir que cURL utilise la librairie
cliente OpenLDAP pour interagir avec les annuaires (fonctionnalité pouvant être désactivée) et qu'elle est limitée
(l'authentification n'est pas assurée par exemple).

ldap[s]://[hôte]:[port]/[dn_base]?[attributs]?[scope]?[filtre]?[extensions]

• hôte : nom du serveur LDAP


• port : le port TCP de connexion. Les valeurs par défaut sont 389 pour une connexion non chiffrée ou TLS et
636 pour une connexion cryptée à l'aide de SSL
• dn_base : nom distingué de l'objet servant de point de référence pour la recherche
• attributs : liste des attributs souhaités séparés par une virgule. Ils seront tous retournés si cette partie est
omise. La valeur spéciale * renvoie en plus les attributs internes.
• scope : une des valeurs suivantes :

• base (par défaut) : seul l'objet désigné par dn_base sera concerné par la recherche
• one : les objets dont le père direct est l'objet indiqué par dn_base seront retenus
• sub : la recherche touchera tous les objets ayant un lien de parenté avec dn_base
• filtre : le filtre de recherche (par défaut : (objectclass=*))
• extensions : liste de fonctionnalités diverses

En guise d'exemple une réimplémentation de la fonction ldap_get_entries entièrement basée sur les extensions cURL
et PCRE :

function curl_ldap_get_entries($url, $timeout = 10)


{
// Exécution de la recherche
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$ldif = curl_exec($ch);
curl_close($ch);

// Traitement du résultat
if ($ldif) {
$objets = preg_split('/^DN:\s*/im', $ldif, -1, PREG_SPLIT_NO_EMPTY);
$res = array('count' => 0);
foreach ($objets as $o) {
$lignes = preg_split('/[\r\n]+/', $o, -1, PREG_SPLIT_NO_EMPTY);
$nbAttr = 0;
foreach ($lignes as $l) {
$l = trim($l);
if (preg_match('/^([^:]+):\s*(.*)$/', $l, $m)) {
if (!in_array($m[1], $res[$res['count']])) {
$res[$res['count']][] = $m[1];
$nbAttr++;
}
$res[$res['count']][$m[1]][] = $m[2];
if (!isset($res[$res['count']][$m[1]]['count'])) {
$res[$res['count']][$m[1]]['count'] = 1;
} else {
$res[$res['count']][$m[1]]['count']++;
}
} else { // DN
$res[$res['count']]['dn'] = $l;
}
}
$res[$res['count']]['count'] = $nbAttr;

- 21 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

$res['count']++;
}
return $res;
}
return FALSE;
}

// Un exemple :
$objets = curl_ldap_get_entries('ldap://ldap.mondomaine.fr/dc=developpez,dc=com??sub');
if ($objets) {
print_r($objets);
}

- 22 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

4 - Alternatives : mise en parallèle avec d'autres méthodes

Ces fonctions ont été développées pour un environnement PHP5 car certaines fonctionnalités ont évoluées (le
deuxième paramètre de la fonction parse_url a été introduit à ce moment) ou bien de nouvelles fonctions sont
apparues (stream_get_wrappers et http_build_query).

4.1 - Vérifier l'existence d'une page

Comme nous l'avons précédemment vu, une requête HEAD permet de connaître le statut d'une page HTTP. Il existe
plusieurs méthodes pour envoyer une telle requête pour ensuite contrôler le code d'erreur retourné comme réponse
parmi les en-têtes :

• avec cURL
• en exploitant la gestion native de flux HTTP par PHP si elle est possible (c'est à dire que la directive
allow_url_fopen doit être à On)
• à l'aide de la fonction fsockopen

function tester_url_http($url, $timeout = 10)


{
if (extension_loaded('curl')) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_NOBODY, TRUE);
if (strpos($url, 'https://') === 0) {
curl_setopt($ch,
CURLOPT_SSL_VERIFYPEER, FALSE); // On ne vérifie que l'existence de la page
}
if (!curl_exec($ch)) {
return FALSE;
}
$ret = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return in_array($ret, array(200, 301, 302));
} elseif (ini_get('allow_url_fopen') && in_array(parse_url($url,
PHP_URL_SCHEME), stream_get_wrappers())) {
$infos = parse_url($url);
$options = array(
'http' => array(
'method' => 'HEAD',
'header' => '',
'timeout' => $timeout // Effectif pour les versions 5.2.1 et supérieures
)
);
if (isset($infos['user'])) {

$options['http']['header'] .= 'Authorization: Basic ' . base64_encode($infos['user'] . ':' . $infos['pass']) . "


\n";
}
$contexte = stream_context_create($options);
@ $fp = fopen($url, 'r', FALSE, $contexte);
if (!$fp) {
return FALSE;
}
$meta = stream_get_meta_data($fp);
fclose($fp);
if (preg_match('#^HTTP/1\.[01] ([0-9]{3})#', $meta['wrapper_data'][0], $m)) {
return in_array($m[1], array(200, 301, 302));
} else {
return FALSE;
}
} elseif (function_exists('fsockopen')) {
$infos = parse_url($url);

- 23 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

if (empty($infos['path'])) {
$infos['path'] = '/';
}
if (!isset($infos['port'])) {
if ($infos['scheme'] == 'http') {
$infos['port'] = 80;
} elseif ($infos['scheme'] == 'https') {
$infos['port'] = 443;
}
}

@ $fp = fsockopen($infos['host'] == 'https' ? 'ssl://' . $infos['host'] : $infos['host'], $infos['port'], $errno


if (!$fp) {
return FALSE;
}
stream_set_timeout($fp, $timeout);
$requete = 'HEAD ' . $infos['path'] . '?' .
(isset($infos['query']) ? $infos['query'] : '') . " HTTP/1.1\r\n";
$requete .= 'Host: ' . $infos['host'] . ':' . $infos['port'] . "\r\n";
if (isset($infos['user'])) {

$requete .= 'Authorization: Basic ' . base64_encode($infos['user'] . ':' . $infos['pass']) . "\r\n";


}
fwrite($fp, $requete . "\r\n");
$entete = fgets($fp, 32);
fclose($fp);
if (preg_match('#^HTTP/1\.[01] ([0-9]{3})#', $entete, $m)) {
return in_array($m[1], array(200, 301, 302));
} else {
return FALSE;
}
} else {
die("Aucune méthode permettant de vérifier l'état d'un document en ligne n'est disponible");
}
}

4.2 - Récupérer le corps d'une page

L'obtention du corps d'une page distante peut se faire de plusieurs manières :

• Avec l'extension cURL


• Avec la gestion de flux HTTP par PHP pour les fonctions capables de lire des fichiers
• Avec la fonction fsockopen, relativement lente, avec laquelle nous devons forger et exploiter les requêtes de
nous-mêmes

Vous trouverez ci-dessous une fonction générique pour obtenir le code source d'une page distante, gérant la méthode
POST ainsi que l'authentification HTTP basique :

function recuperer_page_http($url, $timeout = 10, $nom_local = '', $post = NULL) {


if (extension_loaded('curl')) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
if ($nom_local) {

$fp = fopen($nom_local, 'w') or die("Le fichier '$nom_local' n'a pu être ouvert en écriture");
curl_setopt($ch, CURLOPT_FILE, $fp);
} else {
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
}
if ($post) {
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
}

- 24 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

$ret = curl_exec($ch);
if ($nom_local) {
fclose($fp);
}
curl_close($ch);
if ($ret === FALSE) {
die("Une erreur a été rencontrée : " . curl_error());
}
return $ret;
} elseif (ini_get('allow_url_fopen') && in_array(parse_url($url,
PHP_URL_SCHEME), stream_get_wrappers())) {
$infos = parse_url($url);
$contexte = NULL;
if (isset($infos['user']) || $post) {
$options = array(
'http' => array(
'method' => $post ? 'POST' : 'GET',
'header' => '',
'timeout' => $timeout // Effectif pour les versions 5.2.1 et supérieures
)
);
if (isset($infos['user'])) {

$options['http']['header'] .= 'Authorization: Basic ' . base64_encode($infos['user'] . ':' . $infos['pass']) . "


\n";
}
if ($post) {
$data = http_build_query($post);
$options['http']['header'] .= "Content-type: application/x-www-form-urlencoded\r\n";
$options['http']['header'] .= 'Content-Length: ' . strlen($data) . "\r\n";
$options['http']['content'] = $data;
}
$contexte = stream_context_create($options);
}
if (!$nom_local) {
return file_get_contents($url, FALSE, $contexte);
} else {
$in = fopen($url, 'r', FALSE, $contexte);
stream_set_timeout($in, $timeout);

$out = fopen($nom_local, 'w') or die("Le fichier '$nom_local' n'a pu être ouvert en écriture");
while (!feof($in)) {
fwrite($out, fread($in, 1024));
}
fclose($in);
fclose($out);
}
} elseif (function_exists('fsockopen')) {
$infos = parse_url($url);
if ($nom_local) {

$out = fopen($nom_local, 'w') or die("Le fichier '$nom_local' n'a pu être ouvert en écriture");
}
if (empty($infos['path'])) {
$infos['path'] = '/';
}
if (!isset($infos['port'])) {
if ($infos['scheme'] == 'http') {
$infos['port'] = 80;
} elseif ($infos['scheme'] == 'https') {
$infos['port'] = 443;
}
}

@ $fp = fsockopen($infos['host'] == 'https' ? 'ssl://' . $infos['host'] : $infos['host'], $infos['port'], $errno


if (!$fp) {
return FALSE;
}
stream_set_timeout($fp, $timeout);
$requete = ($post ? 'POST ' : 'GET ') . $infos['path'] . '?' .
(isset($infos['query']) ? $infos['query'] : '') . " HTTP/1.1\r\n";

- 25 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

$requete .= 'Host: ' . $infos['host'] . ':' .


(isset($infos['port']) ? $infos['port'] : '80') . "\r\n";
if (isset($infos['user'])) {

$requete .= 'Authorization: Basic ' . base64_encode($infos['user'] . ':' . $infos['pass']) . "\r\n";


}
if ($post) {
$data = http_build_query($post);
$requete .= "Content-type: application/x-www-form-urlencoded\r\n";
$requete .= 'Content-Length: ' . strlen($data) . "\r\n";
}
fwrite($fp, $requete . "\r\n" . $data);
$buffer = '';
do { // Saut de l'entête HTTP
$buffer .= fgets($fp, 1024);
} while (!feof($fp) && strpos($buffer, "\r\n\r\n") === FALSE);
$buffer = '';
while (!feof($fp)) {
$buffer .= fread($fp, 1024);
}
$buffer = ltrim($buffer);
$pos = strpos($buffer, "\r\n");
$len = hexdec(substr($buffer, 0, $pos));
$buffer = substr($buffer, $pos + strlen("\r\n"), $len);
if ($nom_local) {
fwrite($out, $buffer);
fclose($out);
$buffer = TRUE;
}
fclose($fp);
return $buffer;
} else {
die("Aucune méthode permettant de récupérer la source d'une page n'est disponible");
}
}

4.3 - Recevoir un fichier par FTP

PHP offre différents moyens pour télécharger un fichier via le protocole FTP. A savoir :

• l'extension FTP, le premier moyen qui nous viendrait à l'esprit


• l'extension cURL, comme nous l'avons déjà vu précédemment
• la gestion interne par PHP de flux FTP, ce qui nous permet d'utiliser les traditionnelles fonctions de lecture et
écriture sur des fichiers

Voilà donc une fonction capable de s'adapter à l'environnement afin de tenter de télécharger un fichier à partir d'une
URL FTP :

function recuperer_fichier_ftp($url, $nom_local, $mode_ascii = FALSE, $timeout = 10) {


if (extension_loaded('ftp')) {
$infos = parse_url($url);
if ($infos['scheme'] == 'ftps') {
if (function_exists('ftp_ssl_connect')) {
$conn = ftp_ssl_connect($infos['host'], isset($infos['port']) ? $infos['port'] :
0, $timeout) or die("La connexion n'a pu être établie");
} else {
die("La fonction ftp_ssl_connect n'est pas disponible !");
}
} else {
$conn = ftp_connect($infos['host'], isset($infos['port']) ? $infos['port'] :
0, $timeout) or die("La connexion n'a pu être établie");
}
ftp_login($conn, $infos['user'], $infos['pass']) or die("La phase d'authentifcation a échoué");

- 26 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

ftp_get($conn, $nom_local, $infos['path'], $mode_ascii ? FTP_ASCII :


FTP_BINARY) or die("Le téléchargement a échoué");
ftp_close($conn);
} elseif (extension_loaded('curl')) {
$fp = fopen($nom_local, 'w') or die("Le fichier '$nom_local' n'a pu être ouvert en écriture");
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
if ($mode_ascii) {
curl_setopt($ch, CURLOPT_TRANSFERTEXT, TRUE);
}
if (strpos($url, 'ftps://') === 0) {
// Options supplémentaires liées à SSL à utiliser
}
curl_exec($ch) or die("Une erreur a été rencontrée : " . curl_error());
curl_close($ch);
fclose($fp);
} elseif (ini_get('allow_url_fopen') && in_array(parse_url($url,
PHP_URL_SCHEME), stream_get_wrappers())) {
$in = fopen($url, $mode_ascii ? 'r' : 'rb');
$out = fopen($nom_local, $mode_ascii ? 'w' : 'wb');
while (!feof($in)) {
fwrite($out, fread($in, 1024));
}
fclose($in);
fclose($out);
} else {
die("Aucune méthode permettant de récupérer un fichier par FTP n'est disponible");
}
}

4.4 - Envoyer un fichier par FTP

Similaire en tout point au téléchargement d'un fichier par le biais du protocole FTP, un envoi n'entraîne des
changements que sur le sens des échanges (les flux ouverts en lecture sont maintenant ouverts en écriture et vice-
versa) :

function envoyer_fichier_ftp($url, $nom_local, $mode_ascii = FALSE, $timeout = 10) {


if (is_file($nom_local)) {
if (extension_loaded('ftp')) {
$infos = parse_url($url);
if ($infos['scheme'] == 'ftps') {
if (function_exists('ftp_ssl_connect')) {
$conn = ftp_ssl_connect($infos['host'], isset($infos['port']) ? $infos['port'] :
0, $timeout) or die("La connexion n'a pu être établie");
} else {
die("La fonction ftp_ssl_connect n'est pas disponible !");
}
} else {
$conn = ftp_connect($infos['host'], isset($infos['port']) ? $infos['port'] :
0, $timeout) or die("La connexion n'a pu être établie");
}

ftp_login($conn, $infos['user'], $infos['pass']) or die("La phase d'authentifcation a échoué");


ftp_put($conn, $infos['path'], $nom_local, $mode_ascii ? FTP_ASCII :
FTP_BINARY) or die("L'envoi a échoué");
ftp_close($conn);
} elseif (extension_loaded('curl')) {
$fp = fopen($nom_local, 'r');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($nom_local));
curl_setopt($ch, CURLOPT_UPLOAD, TRUE);
if ($mode_ascii) {
curl_setopt($ch, CURLOPT_TRANSFERTEXT, TRUE);

- 27 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

}
if (strpos($url, 'ftps://') === 0) {
// Options supplémentaires liées à SSL à utiliser
}
curl_exec($ch) or die("Une erreur a été rencontrée : " . curl_error());
curl_close($ch);
fclose($fp);
} elseif (ini_get('allow_url_fopen') && in_array(parse_url($url,
PHP_URL_SCHEME), stream_get_wrappers())) {
$in = fopen($nom_local, $mode_ascii ? 'r' : 'rb');
$out = fopen($url, $mode_ascii ? 'w' : 'wb');
while (!feof($in)) {
fwrite($out, fread($in, 1024));
}
fclose($in);
fclose($out);
} else {
die("Aucune méthode permettant d'envoyer un fichier par FTP n'est disponible");
}
} else {
die("Le fichier '$nom_local' n'existe pas ou n'est pas un fichier régulier");
}
}

- 28 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/
PHP : l'extension cURL par julp (Autres articles)

5 - Conclusion

5.1 - Epilogue

J'espère vous avoir convaincu d'utiliser à votre tour l'extension cURL à la fois pour sa simplicité et sa souplesse dans
la prise en charge des différents protocoles qu'elle est capable de gérer.

Cependant ceux qui n'ont pas la chance de profiter de son support (information que vous pouvez obtenir via la sortie
de phpinfo) devront se tourner vers des alternatives comme fsockopen ou plus simplement vers les traditionnelles
fonctions de lecture de fichiers comme file_get_contents et fopen, fread/fwrite, fclose mais requiert que la directive
allow_url_fopen soit à On (elles prennent habituellement en charge les protocoles HTTP et FTP).

Liens Developpez :
• Le protocole HTTP

Liens externes :
• Documentation officielle de l'extension cURL

- 29 -
Copyright © 2007 - julp. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents,
images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages
et intérêts.
http://julp.developpez.com/php/curl/

S-ar putea să vă placă și