Table des matières

Les Web Services

Fiche


Niveau de difficulté : Expert.
Recommandations : n/c.
A lire aussi : n/c


Inspirez-vous aussi des plugins déjà existants.

«Ou comment externaliser des données de PhpWebGallery»

Cet article se veut le plus abordable possible pour s'adresser au plus grand nombre mais il est tout de même conseillé de disposer de bases sérieuses en PHP


Génération des requêtes

1 - Lancer la page ws.htm dans votre navigateur préféré.

2 - Une page vous demande de préciser la position du script WS (ws.php). Normalement, il doit se trouver sous 'http:\\www.monsite.com\magalerie\ws.php'.

3 - Cliquez alors sur “GO!”

4 - Il s'agit maintenant de choisir la bonne méthode en fonction du résultat désiré. Voici une traduction des termes :

Pour information:

5 - Votre choix fait, il suffit de cliquer sur la méthode pour obtenir le panneau de requêtes associé. Il serait trop long et fastidieux de détailler chaque méthode. Aussi, pour notre exemple, nous choisirons ici la méthode “pwg.categories.getImages” qui nous permettra de d'afficher aléatoirement des images ou leur version miniature selon différents critères.

6 - En utilisant la méthode “pwg.categories.getImages”, nous avons tout d'abord 2 paramètres à renseigner : Le format de la requête (Request format) et le format de la réponse (Response format)

Petit aparté : La méthode pwg.session.login n'accepte que la fonction POST. Par ce biais, on peut envisager d'utiliser une ouverture de session sur un blog (un forum ou autres…) pour s'identifier automatiquement sur la galerie. En partageant les tables contenant les informations des inscrits sur chaque application, on pourrait aussi gérer les nouvelles inscriptions.

FIXME : S'il y en a qui se sentent pour traiter le sujet des XML et autres… ;-)

7 - Dans la partie de droite, nous avons un tableau récapitulant tous les paramètres utilisables pour la méthode sélectionnée. Chaque méthode a un tableau de paramètre différent. Il serait trop long de tout détailler ici. Dans le cadre de notre exemple (méthode “pwg.categories.getImages”), voici les explications des différents filtres :

Dans le cas de catégories multiples la syntaxe est la suivante :

http://fr.piwigo.org/demo/ws.php?method=pwg.categories.getImages&cat_id[]=27&cat_id[]=50

8 - Avec tous ces éléments, il nous est maintenant possible de “jouer” avec l'outil pour tenter d'obtenir le résultat souhaité. La vérification du résultat produit se fait en cliquant sur les liens “Invoke” ou “Invoke (New window)”. Le premier lien affiche le résultat dans le cadre en dessous du tableau de paramètres quant au second, il l'affiche dans une nouvelle fenêtre du navigateur. En poursuivant notre exemple, nous utiliserons les paramètres suivants :

Traduction : “Récupérer, sur une page, 5 images au hasard dans toutes les catégories et sous catégories dont le rapport largeur/hauteur est au moins 1.2 (donc plus larges que hautes). Ceci n'étant bien sur qu'un exemple. On pourrait fixer également f_max_ratio à 1.4, ce qui permettrait d'obtenir les images présentées en mode paysage (en excluant les images carrées, les images de diaporama et les image en mode portrait.”

Autre exemple :

Traduction : “Récupérer, sur une page, 5 images au hasard, vues au moins 500 fois, dans toutes les catégories et sous catégories.” Ce qui permet d'afficher un nombre limité d'images “Les plus regardées”. A l'inverse, on peut ne mettre qu'un f_max_hit à 50 et tant que des images n'auront pas été regardées au moins 50 fois, elles seront présentées, ce qui permet de présenter “Les plus récentes” en y intégrant “Les moins regardées”.

9 - Un clic sur “Invoke” et on obtient un tableau sérialisé des données trouvées par la requête. Comme on a spécifié “Random” dans le paramètre “order”, on ne devrait pas retrouver deux fois le même résultat. Sauf, bien entendu, s'il n'y a pas assez d'images répondant aux critères. Le tableau est représenté sous la forme :

a:2:{s:4:"stat";s:2:"ok";s:6:"result";a:1:{s:6:"images";
(...)
"page_url";s:72:"http://www.monsite.com/magalerie/picture.php?/[id]/category/[id]";}}}}}}}

10 - Pas très évident de vérifier le bon fonctionnement de la requête sous cette forme, je vous l'accorde. Mais vous pouvez faire des essais en réduisant, par exemple, le nombre d'images à retourner. Vous pouvez passer en présentation “REST (xml)” ce sera plus simple à contrôler. Mais dans notre cas, il faut formater le résultat pour y comprendre quelque chose. Avant tout, quelques définitions :

- a:x -> "a" pour "array" ou tableau suivi par x représentant le nombre d'éléments dans le tableau.
    Exemple : a:2 = "tableau de 2 éléments"

- s:x:"$" -> "s" pour "String" ou chaine suivi par x représentant le nombre de caractères de la chaine et $, le contenu de la chaine.
    Exemple : s:4:"stat" = "Chaine de 4 caractères qui sont "stat"

- i:x -> "i" pour "Integer" ou entier suivi de la valeur de l'entier.
    Exemple : i:100 = "Un entier de valeur 100"

- N -> équivalent à NULL.

- Les tableaux sont délimités par "{}".

- Les champs du tableau sont délimités par ";".

- Une donnée complète du tableau est composée du nom de la donnée et de sa valeur.
    Exemples : s:4:"stat";s:2:"ok";
               s:4:"page";i:0;

* Ci-dessous, un exemple de ce que cela donne avec les explications qui vont bien.

a:2:{
	s:4:"stat";s:2:"ok"; <- le statut de la requête est OK
	s:6:"result";a:1:{ <- le résultat commence ici
		s:6:"images";a:4:{ <- le tableau des images qui contient 4 éléments
			s:4:"page";i:0; <- élément #1 : le nombre de pages pour afficher les éléments (images)
			s:8:"per_page";i:100; <- élément #2 : le nombre d'éléments (images) par page
			s:5:"count";i:11; <- élément #3 : le compte du nombre d'éléments (images) trouvés.
			s:8:"_content";a:11:{ <- élément #4 : Qui ouvre aussi un tableau de 11 éléments détaillant le contenu de la requête, c'est çà dire les images proprement dites
				i:0;a:10:{ <- Première image trouvée dont les données sont dans un tableau de 10 éléments
					s:2:"id";i:4460; <- l'identifiant (ID) de l'image #1 en base de données
					s:5:"width";i:504; <- la largeur de l'image #1
					s:6:"height";i:699; <- la hauteur de l'image #1
					s:3:"hit";i:35; <- le nombre de fois que l'image #1 a été vue
					s:4:"file";s:38:"image1.jpg"; <- le fichier phyqique de l'image #1
					s:4:"name";s:23:"nom_image_1"; <- le nom représentant l'image #1
					s:7:"comment";N; <- le commentaire associé à l'image #1 (IPTC). Il ne s'agit pas des commentaires déposés par les visiteurs de la galerie.
					s:6:"tn_url";s:116:"http://www.monsite.com/magalerie/./galleries/Catégorie1/thumbnail/TN-image1.jpg";  <- le chemin complet pour accéder à la miniature de l'image #1
					s:11:"element_url";s:103:"http://www.monsite.com/magalerie/./galleries/Catégorie1/image1.jpg"; <- Le chemin complet pour accéder à l'image #1
					s:10:"categories";a:1:{ <- les informations sur la (les) catégorie(s) hébergeant l'image #1.
							i:0;a:3:{ <- Ici une seule catégorie donc 1 élément qui ouvre un tableau de 3 éléments
								s:2:"id";i:227; <- l'identifiant (ID) de la catégorie
								s:3:"url";s:65:"http://www.monsite.com/magalerie/index.php?/category/227"; <- le chemin complet pour accéder à racine de la catégorie
								s:8:"page_url";s:72:"http://www.monsite.com/magalerie/picture.php?/4460/category/227"; <- le chemin complet pour accéder aux pages de la catégorie (cas où il y aurait plusieurs pages)
								}
							}
						}
				i:1;a:10:{ <- Et c'est reparti pour l'image #2 - Même principe - Et ainsi de suite jusqu'à l'image #11 puisque c'est le nombre d'éléments retournés par la requête.
					s:2:"id";i:4458;
					s:5:"width";i:432;
					s:6:"height";i:653;
					s:3:"hit";i:30;
					s:4:"file";s:28:"image2.jpg";
					s:4:"name";s:13:"nom_image_2";
					s:7:"comment";N;
					s:6:"tn_url";s:106:"http://www.monsite.com/magalerie/./galleries/Catégorie1/thumbnail/TN-image2.jpg";
					s:11:"element_url";s:93:"http://www.monsite.com/magalerie/./galleries/Catégorie1/image2.jpg";
					s:10:"categories";a:1:{
						i:0;a:3:{
							s:2:"id";i:227;
							s:3:"url";s:65:"http://www.monsite.com/magalerie/index.php?/category/227";
							s:8:"page_url";s:72:"http://www.monsite.com/magalerie/picture.php?/4458/category/227";
								}
							}
						}
(...)

Pas très évident de lire directement un tel résultat, il est vrai.
Vous pouvez passer en présentation “REST (xml)” ce sera plus simple à contrôler. Toutefois essayez donc la présentation JSON (un grand standard des Web Services):

{"stat":"ok","result": 
{"images": {"page":0,"per_page":"100","count":11,"_content": 
[ {"id":4460, "width":504, "height":699, "hit":35, "file":"image1.jpg",
"name":"nom_image_1", "comment":null,
"tn_url":"http:\/\/www.monsite.com/magalerie\/.\/galleries\/Catégorie1\/thumbnail\/TN-image1.jpg",
"element_url":"http:\/\/www.monsite.com/magalerie\/.\/galleries\/Catégorie1\/image1.jpg",
"categories": [ {"id":227,
"url":"http:\/\/www.monsite.com/magalerie\/index.php?\/category\/227",
"page_url":"http:\/\/www.monsite.com/magalerie\/picture.php?\/4460\/category\/227" 
} ] } 
...

Juste un tout petit peu plus facile à lire, peut-être.
Ainsi pour retrouver l'élément_url dans une variable php (format=php) en supposant que le résultat de la requête soit dans $thumbc. Nous aurons:
$image_address = $thumbc[“result”][“images”][“_content”][0][“element_url”];
0 correspondra à la première image, 1 à la seconde comme dans tout tableau php.
En savoir plus sur la syntaxe JSON.

11- Lorsque la requête est au point, notez les paramètres pour qu'ils puissent être appelés par un script PHP dans la page externe destinée à recevoir le résultat de la requête. Pour notre exemple, nous aurons :

http://www.monsite.com/magalerie/ws.php?method=pwg.categories.getImages&format=php&recursive=true&order=random&f_min_ratio=1.2&f_with_thumbnail=true&per_page=5&page=0
Lien vers ws.php -> http://www.monsite.com/magalerie/ws.php
Passage en paramètre de la méthode ->                      ?method=pwg.categories.getImages

Définition du format de sortie ->                          &format=php

Paramètres de la requête ->                                &recursive=true
                                                           &order=random
                                                           &f_min_ratio=1.2
                                                           &f_with_thumbnail=true
                                                           &per_page=5
                                                           &page=0

Utilisation des webservices

Dans une page PHP externe

1 - Je passe sur la position d'insertion du code PHP dans la page ou du script devant accueillir le résultat de la requête WS. Chacun trouvera l'endroit idéal qui lui conviendra selon ses besoins. Pour notre exemple, nous envisagerons le cas simple d'une page HTML formatée ou non avec des CSS et accueillant dans une partie x l'affichage de nos 5 images.

2 - Voici un exemple de code utilisable. Il sera documenté et expliqué à la suite. Ce code est modulable et n'est en aucune façon une référence en soit. Ce n'est que pour illustrer l'exemple WS considéré (merci à VDigital pour cette solution dont il est l'auteur):

<?php
// initialisation de la session
$session = curl_init(); /* (a) */
 
// configuration des options
/* (b) */
curl_setopt($session, CURLOPT_URL,
"http://www.monsite.com/magalerie/ws.php?method=pwg.categories.getImages&format=php&recursive=true&order=random&f_min_ratio=1.2&f_with_thumbnail=true&per_page=5&page=0");
curl_setopt($session, CURLOPT_HEADER, 0);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
 
// exécution de la session
$response = curl_exec($session); /* Ici nous réceptionnons le tableau sérialisé de la requête (c) */
$thumbc = unserialize($response);/* que nous "désérialisons" (d) */
 
curl_close($session); /* fermeture des ressources (e) */
 
if ($thumbc["stat"]=='ok') /* Réponse correcte ? (f) */
 {
  for ($i=0;$i<$thumbc["result"]["images"]["count"];$i++) /* (g) */
   {
    $picture = $thumbc["result"]["images"]["_content"][$i]; /* (h) */
 
    // dans picture nous avons :  id, width, height, hit, file, name, comment, tn_url, element_url
/* (i) */
 
    $HTML_txt = '<a href="http://www.monsite.com/magalerie/picture.php?/'
        . $picture['id'].'" title="'.$picture['name'].'">'.'<img src="'
        . $picture['tn_url'].'" alt="'.$picture['name']
        . '" /></a><span class="caption">['.$picture['width'].'x'
        . $picture['height'].'] &nbsp; - &nbsp;'.'Hits : '
        . $picture['hit'].'</span><br/>';
    echo $HTML_txt;
    }
  }
?>

3 - Explications du code ci-dessus :

Pour obtenir le résultat de la requête WS, nous devons utiliser le jeu de fonctions curl. Il est néanmoins possible d'arriver au même résultat en utilisant file_get_contents() mais cette fonction n'est pas admise par tous les hébergeurs. Pour plus de détails sur ces fonctions, se reporter à la doc de PHP.

a) On commence par initialiser une variable de session sur la fonction curl…

b) … Et on établit les options relatives dont, notamment, l'URL de la requête élaborée dans le paragraphe précédent.

c) Le résultat de la requête est récupéré par curl_exec($session) et stocké dans une variable…

d) … Mais il s'agit d'un tableau de valeurs en série qu'il faut remettre en forme. La fonction unserialize($response) se charge de cela et stocke le tableau dans une nouvelle variable.

e) Pour continuer les traitements, on ferme la session de la requête initiale.

f) Pour être certain de ne pas afficher n'importe quoi si la requête ne retourne rien, on teste si le champ “stat” est bien à “OK”.

g) On isole chaque élément du tableau des résultats (comprendre les images)…

h) … Et pour chaque élément, on “charge” une variable $picture qui contiendra toutes les infos relatives à chaque image.

i) Il ne reste plus qu'à “partir à la pêche” aux infos et à les placer sous format HTML dans une variable d'affichage.

Simple, non ?… Non, pas simple, mais très puissant ! En jouant avec les différentes requêtes WS et en arrangeant le code PHP à ses besoins, on peut afficher à peu près n'importe quelle information présente dans la galerie.

Dans un script Perl

Je vous propose un script Perl, en ligne de commande, qui va récupérer la liste des tags et les affiche dans la sortie standard.

Première version du script, sans être connecté.

#!/usr/bin/perl
 
use strict;
use warnings;
 
use JSON;
use LWP::UserAgent;
use Text::ASCIITable;
 
our $ua = LWP::UserAgent->new;
$ua->cookie_jar({});
 
my %conf;
$conf{limit} = 10;
$conf{base_url} = 'http://demo.phpwebgallery.net/ws.php';
$conf{partner_key} = undef;
$conf{response_format} = 'json';
$conf{username} = 'plegall';
$conf{password} = 'secret_password';
 
my $result = undef;
my $query = undef;
 
binmode STDOUT, ":encoding(utf-8)";
 
$query = pwg_ws_get_query(
    method => 'pwg.tags.getList',
    sort_by_counter => 'true',
);
 
$result = $ua->get($query);
my $tag_result = from_json($result->content);
my $t = Text::ASCIITable->new({ headingText => 'Tags' });
$t->setCols('id','counter','name');
 
my $tag_number = 1;
foreach my $tag_href (@{ $tag_result->{result}{tags} }) {
    $t->addRow(
        $tag_href->{id},
        $tag_href->{counter},
        $tag_href->{name}
    );
 
    last if $tag_number++ >= $conf{limit};
}
print $t;
 
sub pwg_ws_get_query {
    my %params = @_;
 
    my $query = $conf{base_url}.'?format='.$conf{response_format};
 
    if (defined $conf{partner_key}) {
        $query .= '&partner='.$conf{partner_key};
    }
 
    foreach my $key (keys %params) {
        $query .= '&'.$key.'='.$params{$key};
    }
 
    return $query;
}

The result is:

$ time perl piwigo_remote_disconnected.pl 
.---------------------------------------.
|                  Tags                 |
+-----+---------+-----------------------+
| id  | counter | name                  |
+-----+---------+-----------------------+
|  17 |     116 | Nature                |
|  34 |      83 | Architecture          |
|  24 |      63 | Culture & Communities |
|  23 |      55 | Flowers               |
| 124 |      53 | Square                |
|   8 |      53 | Animals               |
| 135 |      42 | Ref. Wikipedia        |
|  12 |      37 | Styles                |
| 114 |      34 | Islands               |
|  58 |      30 | Celebrations          |
'-----+---------+-----------------------'

real    0m1.554s
user    0m0.288s
sys     0m0.004s

J'utilise JSON comme format de réponse, car il existe un module CPAN qui se charge de transformer une chaîne JSON en une structure de données Perl. LWP::UserAgent s'occupe de simuler un navigateur, c'est un robot qui parcourt une page web. Text::ASCIITable sert à afficher les informations de manière convenable sans se fatiguer.

Maintenant je souhaite voir la liste des tags telle que je la vois lorsque je suis connecté sur mon site personnel. Il va donc falloir que le script soit authentifié avant de faire la demande de la liste des tags.

#!/usr/bin/perl
 
use strict;
use warnings;
 
use JSON;
use LWP::UserAgent;
use Text::ASCIITable;
 
our $ua = LWP::UserAgent->new;
$ua->cookie_jar({});
 
my %conf;
$conf{base_url} = 'http://localhost/~pierrick/piwigo/trunk/ws.php';
$conf{partner_key} = 'youhou';
$conf{response_format} = 'json';
$conf{username} = 'pierrick';
$conf{password} = 'very_secret_password';
$conf{limit} = 10;
 
my $result = undef;
my $query = undef;
 
binmode STDOUT, ":encoding(utf-8)";
 
# TODO : don't connect at each script call, use the session duration instead.
my $form = {
    method => 'pwg.session.login',
    username => $conf{username},
    password => $conf{password},
};
 
$result = $ua->post(
    $conf{base_url}.'/ws.php?partner=youhou&format=json',
    $form
);
 
# print "\n", $ua->cookie_jar->as_string, "\n";
 
$query = pwg_ws_get_query(
    method => 'pwg.tags.getList',
    sort_by_counter => 'true',
);
 
$result = $ua->get($query);
my $tag_result = from_json($result->content);
my $t = Text::ASCIITable->new({ headingText => 'Tags' });
$t->setCols('id','counter','name');
 
my $tag_number = 1;
foreach my $tag_href (@{ $tag_result->{result}{tags} }) {
    $t->addRow(
        $tag_href->{id},
        $tag_href->{counter},
        $tag_href->{name}
    );
 
    last if $tag_number++ >= $conf{limit};
}
print $t;
 
$query = pwg_ws_get_query(
    method => 'pwg.session.logout'
);
$ua->get($query);
 
sub pwg_ws_get_query {
    my %params = @_;
 
    my $query = $conf{base_url}.'?format='.$conf{response_format};
 
    if (defined $conf{partner_key}) {
        $query .= '&partner='.$conf{partner_key};
    }
 
    foreach my $key (keys %params) {
        $query .= '&'.$key.'='.$params{$key};
    }
 
    return $query;
}

La différence avec le script précédent, c'est l'appel à la méthode pwg.session.login en début de script et à la méthode pwg.session.logout en fin de script (pour purger la session au niveau du serveur, mais idéalement, il faudrait réutiliser la session existante).

Le “user agent” a associé un cookie à la session lors de l'appel à la méthode pwg.session.login. Ce cookie ne persiste pas, à la fin du script, c'est perdu (il suffirait de le sauver, mais ce n'est pas l'objet de la présente démonstration).

Sécurisation des Web Services

Chapitre obsolète avec Piwigo 2.0.0 et +

Malheureusement, les WS peuvent permettre des accès indésirables à la galerie. Pour éviter de tels désagréments et autres effets de bord, on va mettre en œuvre des mesures de sécurisation du service.

1 - On commence par renommer son PWG/tools/ws.htm en autre chose : walouM-ws.htm ou en biquet9-ws.htm.

2 - Ensuite, il faut activer le fonctionnement sécurisé de WS. Pour cela:

// On Access control false / Admim Web Service need Php cURL extension
// Controls are done on public basis or 
// if connected on member authorization basis
$conf['ws_access_control'] = true;

Le fichier est, bien entendu, à “uploader” sur son serveur d'hébergement. A partir de ce moment, le WS établi précédemment ne fonctionnera plus. C'est normal !

3 - Se rendre dans le panneau d'administration de sa galerie. On y trouvera un nouveau menu “Services Web” dans le menu “Spéciales”. C'est là qu'il faut se rendre pour la suite des opérations.

4 - Le menu “Service Web” va nous permettre de générer une clé spécifique pour chaque WS en fonction. De plus, il est possible de partager un WS avec un site partenaire que l'on n'administre pas forcément. Une clé sera alors également générée et donnée au partenaire en question pour qu'il puisse faire fonctionner le WS sur son site. Voici un exemple simple et concret :

On valide et la clé est active.

5 - Il faut maintenant reprendre le WS que nous avons créé dans les paragraphes précédents pour le rendre à nouveau opérationnel. Pour cela, il suffit d'ajouter le paramètre partner dans la requête. Dans la continuité de notre exemple, nous ajoutons &partner=Cl3PourW3bSvc1 :

<?php
// initialisation de la session
$session = curl_init();
 
// configuration des options
curl_setopt($session, CURLOPT_URL,
"http://www.monsite.com/magalerie/ws.php?method=pwg.categories.getImages&partner=Cl3PourW3bSvc1&format=php&recursive=true&order=random&f_min_ratio=1.2&f_with_thumbnail=true&per_page=5&page=0");
curl_setopt($session, CURLOPT_HEADER, 0);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
(...)
?>

Un rapide contrôle permettra de vérifier que tout est à nouveau opérationnel.

6 - Mais ce n'est pas tout. Le fait de passer en mode sécurisé a invalidé le fonctionnement de notre ex-fichier PWG/tools/ws.htm (renommé à l'étape 1). Il faut maintenant lui administrer quelques corrections pour qu'il soit de nouveau utilisable.

Mais avant cela, il conviendra de créer une nouvelle clé, distincte de celles déjà créées pour les différents WS en fonction, qui sera celle de l'administrateur (ne sera pas diffusée à des tiers). En effet, seul l'administrateur devrait pouvoir utiliser ws.htm qui, je le rappelle, est destiné à effectuer les recherches initiales pour élaborer la requête WS.

Ensuite on édite le fichier ws.htm (Insérer partner=##### en remplaçant # par la clé) :

Ligne 103 : parameters:'partner=#####&format=json&method=reflection.getMethodList'

Ligne 140 : parameters:'partner=#####&format=json&method=reflection.getMethodDetails&methodName='

Ligne 191 - Ajouter : reqUrl += ”&partner=#####”;

7 - Enfin, quelques recommandations :

Détails des paramètres de sécurisation

Nous venons de voir un exemple simple et concret, mais reprenons ces paramètres.

Condition de fonctionnement : $conf['ws_access_control']

Clé confidentielle (Obligatoire) : Cette clé est unique et à partager avec votre partenaire.
Notre conseil: La clé doit être assez longue ( 8 caractères par exemple), et être assez complexe (avec des chiffres, des majuscules et minuscules, et des caractères spéciaux). Par exemple: “P!32r!k L3 G@2l”. Ce champ est masqué de tout accès en mode conseillé actif (Adviser).
Pensez qu'un de vos partenaire peut avoir plusieurs clés, mais que seules les restrictions de la clé utilisée lors de l'appel seront actives.

Cible (Facultatif) : Soit une liste d'identifiants d'images comme ceci
list/277,275,142,235,178,190,204,236-238,253,268,276,285,41,73
ou une liste de catégories comme : cat/16,32,21
ou encore une liste de tags : tag/22,61,36
Tout liste d'identifiants sera réduite à sa plus simple expression : list/41,73,142,178,190,204,235-238,253,268,275-277,285
Notre conseil: Prévoir une catégorie pour chaque partenaire réel. Ce point sera réexpliqué ultérieurement.

Accès restreint (Facultatif) : Si vous souhaitez limiter votre partenaire à une méthode précise, c'est une liste pré-établie, donc simple à comprendre. Notre conseil: ne pas limiter les méthodes sauf pour des cas très particuliers. Le forum est là pour vous éclairer si nécessaire.

Limite de transmission : Nombre d'images maximum adressées à votre partenaire à chacune de ses requêtes.

Durée : A partir de maintenant, indiquez la disponibilité en jours.

Commentaire : Vous permet de décrire qui se trouve derrière ce Service Web, de façon plus claire pour vous. N'oubliez pas qu'un Administrateur en mode conseiller peut lire le contenu de ce commentaire.

FIXME : D'éventuelles autres recommandations ?