IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Piloter WebDAV en C#

Image non disponible

Pour faire de l'AJAX, ou parser des pages sur la toile, dans le domaine du web, on connait bien notre chère HTTPRequest pour faire des GET ou POST. Découvrez dans cet article qu'il est possible à travers WebDAV d'étendre les possibilités du protocole HTTP pour faire de la gestion de ressource Web.

Cet article existe également en version VBScript.

N'hésitez pas à commenter cet article ! Commentez Donner une note à l´article (5)

Article lu   fois.

L'auteur

Profil Pro

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

WebDAV (Web-based Distributed Authoring and Versioning) est une extension du protocole HTTP/1.1.
Il permet de gérer des fichiers sur un serveur distant et comprend comme fonction principale : l'écriture, la lecture, le listage et le déplacement des ressources distantes.
Le protocole offre des avantages dans plusieurs aspects.

  • Par rapport à un FTP, celui-ci est plus sécurisé. Possibilité d'encapsulation dans un canal sécurisé HTTPS/SSL, cryptage des mots de passe, et authentification Kerberos.
  • Par rapport au système de fichiers Windows, le protocole peut gérer des chemins longs de plus de 255 caractères.
  • Reposant sur le protocole HTTP, il peut utiliser les numéros de ports classiques ce qui évite toutes reconfigurations des firewalls.


Au cours de cet article, nous illustrerons l'implémentation des principales fonctions du protocole avec des exemples en C# sur un serveur WebDAV IIS (Information Internet Service). On finira avec la problématique du codage html dans les URL et l'implémentation à faire.

II. Essentiel sur le protocole WebDAV

II-A. Les méthodes HTTP et WebDAV

Comme vu en introduction, WebDAV est une extension de HTTP implémentant des méthodes supplémentaires, comme l'écriture (PUT), la copie (COPY).
Vous trouverez ci-dessous la liste des principales méthodes HTTP possibles par un serveur WebDAV.

Méthodes

Définitions

OPTIONS

Définit les options de communications

GET

Obtient une ressource

HEAD

Obtient uniquement les informations d'entête d'une ressource

DELETE

Supprime le fichier distant

PUT

Crée ou met à jour un fichier

POST

Obtient une ressource et transmet les données dans l'entête de la requête

COPY

Copie un fichier distant vers une autre destination côté serveur

MOVE

Déplace ou renomme un fichier distant

MKCOL

Crée un dossier distant

PROPFIND

Récupère les propriétés d'une ressource distante

PROPPATCH

Définit les propriétés d'une ressource distante

LOCK

Verrouille une ressource distante

UNLOCK

Déverrouille une ressource distante

SEARCH

Recherche des ressources à l'aide de requête SQL


En plus de ces méthodes, on trouve aussi BCOPY, BDELETE, BMOVE, BPROPFIND, BPROPPATCH qui permettent les mêmes opérations, mais en travaillant avec plusieurs ressources à la fois.

II-B. Les réponses HTTP et WebDAV

Comme http, les réponses aux requêtes contiennent un statut se composant d'un code et d'une description. Le code de statut informe de l'état de la requête envoyée et peut être testé afin de prévoir les cas alternatifs comme l'échec de connexion, les redirections et autres (voir liste code retour).

Vous trouverez la liste des codes réponses HTTP et leurs descriptions à l'adresse suivante : http://fr.wikipedia.org/wiki/Liste_des_codes_HTTP

On peut noter aussi que le protocole WebDAV a des codes de statut qui lui sont propres (voir liste ci-dessous) :

Code statut

Statut

Description

102

Processing

Traitement WebDAV en cours

207

Multistatus

Réponses multiples

210

Content Different

La copie de la ressource cotée client diffère de celle du serveur

422

Unprocessable entity

L'entité fournie avec la requête est incompréhensible ou incomplète.

423

Locked

L'opération ne peut avoir lieu, car la ressource est verrouillée.

424

Method failure

Une méthode de la transaction a échoué

507

Insufficient storage

Espace insuffisant pour modifier les propriétés ou construire la collection


Extrait de la référence Wikipédia (détail dans le lien ci-dessus)

II-C. Interprétation des codes HTML

Lorsqu'un nom de fichier est converti en URL, les caractères spéciaux ou étendus doivent être convertis en code html.

Vous trouverez ci-dessous une liste des codes caractères utilisés par les serveurs WebDAV. Cette liste ne représente qu'une partie de tous les codes internationaux gérés par Unicode.

Table des codes caractères :

Code HTML

Code ASCII étendu

Code HTML

Code ASCII étendu

Code HTML

Code ASCII étendu

 

(espace)

á

A

Ï

Ï

%

%

í

í

Ì

Ì

Ç

Ç

ó

ó

¯

¯

ü

Ü

ú

ú

Ó

Ó

é

é

ñ

ñ

ß

ß

â

â

Ñ

Ñ

Ô

Ô

ä

ä

ª

ª

Ò

Ò

à

à

º

º

õ

Õ

å

å

¿

¿

Õ

Õ

ç

ç

¬

v

µ

µ

ê

ê

½

½

þ

Þ

ë

ë

¼

¼

Þ

Þ

è

è

¡

¡

Ú

Ú

ï

ï

« 

«

Û

Û

î

î

»

»

Ù

Ù

ì

ì

Á

Á

ý

Ý

Ä

Ä

Â

Â

Ý

Ý

Å

Å

À

À

´

´

É

É

©

©

±

±

æ

Æ

¢

¢

¾

¾

Æ

Æ

¥

¥

ô

Ô

ã

ã

§

§

ö

Ö

Ã

Ã

÷

÷

ò

Ò

¤

¤

¸

¸

û

Û

ð

ð

°

°

ù

Ù

Ð

Ð

¨

¨

ÿ

?

Ê

Ê

·

?

Ö

Ö

Ë

Ë

¹

¹

Ü

Ü

È

È

³

³

¥

¥

Í

Í

²

²

£

£

Î

Î

¦

¦

ƒ

?

Œ

?

®

®


À présent, implémentons nos fonctions de conversions.
Voici deux méthodes pouvant être implémentées. Ce code est montré à titre d'exemple. Dans le traitement d'un grand nombre de chaines URL ou chemins, il est conseillé d'utiliser une expression régulière afin de convertir uniquement les codes présents dans la chaine URL ou Pathx.

Code C#
Sélectionnez
public string HTTPDecodeToRelativePath(string Url)
{
    return Url.Replace(@"\", "/").Replace("%", "%").Replace("Ç", "Ç");
}

Ces trois conversions sont données à titre d'exemple, pour une prise en charge complète de tous les codes, vous serez amené à implémenter toutes les combinaisons possibles.

Pour l'encodage, dans le namespace System.Web.HttpServerUtility, on utilise la méthode HtmlEncode de la classe HttpServerUtility.

 
Sélectionnez
HttpServerUtility.HtmlEncode(Pathx) ;

III. l'Implémentation

III-A. Lecture d'une collection WebDAV (Parcourir un dossier)

Le parcours d'un répertoire distant se fait avec une méthode GET en HTTP au niveau de la requête Web.

III-A-1. Les librairies HTTP

En CSharp, on utilise dans le namespace System.IO, la classe HttpWebRequest. La requête est transmise à l'exécution de la fonction GetResponse().

Code C#
Sélectionnez
req.Method = "GET";
WebResponse webResp = req.GetResponse();

III-A-2. L'authentification

Dans le cas d'un serveur sécurisé par authentification, il est également possible de renseigner un identifiant et un mot de passe qui seront contenus dans la requête transmise.

Code C#
Sélectionnez
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(CourantHREF);
req.Method = "GET";
NetworkCredential networkCredential = new NetworkCredential(sUserName, sPassword);
req.Credentials = networkCredential;

En CSharp on initialise la classe NetworkCredential avec en argument du constructeur l'identifiant puis le mot de passe. La classe doit ensuite être affectée à la propriété Credentials de la classe HttpWebRequest.

Ces classes sont présentes dans le namespace System.Net.

III-A-3. Réponses HTML

La requête GET est transmise au serveur qui renvoie ensuite un flux HTML contenant des liens <a href=""> (voir exemple ci-dessous).

Réponse renvoyée par le serveur
Sélectionnez
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>workflow - /testwebdav/</title>
</head>
<body>
    <h1>
        workflow - /testwebdav/</h1>
    <hr>
    <pre>
    <a href="/">[Vers le répertoire parent]</a>
    <br><br>     mercredi 30 juillet 2008    11:17       &lt;rép&gt; 
    <a href="/testwebdav/Log/">Log</a>
    <br>        mardi 29 juillet 2008    17:01          132 
    <hr>
</body>
</html>

III-A-4. Récupérations des liens avec expressions régulières

La récupération des liens peut se faire à l'aide d'une expression régulière qu'on applique sur le flux contenu dans sResponse :

Code C#
Sélectionnez
Regex linkRegExp = new Regex(@"<A\b[^>]*>(.*?)</A>", RegexOptions.Multiline | RegexOptions.IgnoreCase);
MatchCollection mainMatches = linkRegExp.Matches(sResponse);

L'expression régulière traite les occurrences du serveur Microsoft IIS 6.0. Dans le cas d'un autre type de serveur, on sera amené à redéfinir le pattern.

III-A-5. Parcours du dossier WebDAV

Cela donne pour le parcours complet d'un dossier :

Code C#
Sélectionnez
public void ParcourirLiens(string CourantHREF, string sUserName, string sPassword)
{
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(CourantHREF);
    req.Method = "GET";

    // s'authentifie
    if (!String.IsNullOrEmpty(sUserName))
    {
        NetworkCredential networkCredential = new NetworkCredential(sUserName, sPassword);
        req.Credentials = networkCredential;
    }

    WebResponse webResp = req.GetResponse();
    Stream stream = webResp.GetResponseStream();
    StreamReader sr = new StreamReader(stream);
    String sResponse = sr.ReadToEnd();

    Regex linkRegExp = new Regex(@"<A\b[^>]*>(.*?)</A>", RegexOptions.Multiline | RegexOptions.IgnoreCase);
    MatchCollection mainMatches = linkRegExp.Matches(sResponse);
    foreach (Match linkMatch in mainMatches) // parcours les liens
    {
        String strLink = linkMatch.Value;
    }
    webResp.Close();
}

III-A-6. Création / mise à jour d'un fichier

La mise à jour et la création d'un nouveau fichier se font grâce à la méthode PUT. Avant envoi, le fichier à transmettre doit être lu puis stocké dans un tableau d'octets.

Pour ce travail, on va implémenter une méthode getFileBytes pour lire le flux et le retourner.

Code C#
Sélectionnez
Byte[] getFileBytes(string Fichier)
{
     // lit le flux en mode binaire
     Stream stream = new FileStream(Fichier, FileMode.Open);
     BinaryReader binReader = new BinaryReader(stream);
     Byte[] result = binReader.ReadBytes((Int32)stream.Length); // lit tous
     stream.Close();

     return result;
}

Puis on transmet le tableau de Bytes de la fonction dans le flux de la WebRequest.

Le serveur renvoie le code 200 (OK) lorsque le fichier est mis à jour. Si le fichier n'existe pas alors celui-ci est créé et le serveur renvoie le code 201 (Create).

Code C#
Sélectionnez
public HttpStatusCode MettreAJour(string Fichier, string Url, string sUserName, string sPassword)
{
    string bSuccess;
    HttpStatusCode iStatus;
    string sStatus;
    string sResponse;

    Byte[] Data = getFileBytes(Fichier);

    string FileNameUrl;
    FileNameUrl = Url + "/" + Path.GetFileName(Fichier);

    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
    req.Method = "PUT";
    req.ContentLength = Data.LongLength;

    // s'authentifie
    if (!String.IsNullOrEmpty(sUserName))
    {
        NetworkCredential networkCredential = new NetworkCredential(sUserName, sPassword);
        req.Credentials = networkCredential;
    }

    Stream stream = req.GetRequestStream();
    stream.Write(Data, 0, Data.Length);
    stream.Close();
    
    HttpWebResponse response =  (HttpWebResponse)req.GetResponse();
    iStatus = response.StatusCode;
    sStatus = response.StatusDescription;

    if (iStatus == HttpStatusCode.OK || iStatus == HttpStatusCode.Created)
        Console.WriteLine(String.Format("PUT: OK    Resultat = {0}: {1}", iStatus, sStatus));
    else if (iStatus == HttpStatusCode.Unauthorized)
        Console.WriteLine("PUT WEBDAV: Vous n'avez pas les permissions requises! Contactez l'administrateur du système");
    else
        Console.WriteLine(String.Format("PUT: Echec Resultat = {0}: {1}", iStatus, sStatus));

    response.Close();

    // Retourne le statut
    return iStatus;
}

III-A-7. Création d'un répertoire distant

La création de répertoires web se fait avec la méthode MKCOL, le nom du répertoire est renseigné directement par l'url.

Le serveur nous renvoie, en réponse, le code statut 201 (Create) en cas de succès.

Code C#
Sélectionnez
public HttpStatusCode CreerDossierWebDAV(string Url, string sUser, string sPassword)
{
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
    req.Method = "MKCOL";

    // s'authentifie
    if (!String.IsNullOrEmpty(sUser))
    {
        NetworkCredential networkCredential = new NetworkCredential(sUser, sPassword);
        req.Credentials = networkCredential;
    }
    // envoie requete / reception réponse
    HttpWebResponse webResp = (HttpWebResponse)req.GetResponse();

    if (webResp.StatusCode == HttpStatusCode.Created)
        Console.WriteLine("Le répertoire a été créé. Status " + webResp.StatusDescription);
    else
        Console.WriteLine("Le répertoire n'a pas été créé. Status " + webResp.StatusDescription);

    webResp.Close();
    return webResp.StatusCode;
}

III-A-8. Lecture des propriétés d'une ressource WebDAV

Pour lire les propriétés d'une ressource, on envoie avec la méthode PROPFIND avec comme url la cible dont les propriétés sont demandées. Dans le corps de message, on peut renseigner les propriétés que l'on désire recevoir.

Exemple de propriétés souhaitées :

Flux XML
Sélectionnez
<?xml version=\"1.0\"?>
<d:propfind xmlns:d='DAV:'>
    <d:prop>
        <d:displayname/><d:getcontentlength /><d: creationdate />
        <d:getlastmodified /><d:ishidden /><d:iscollection />
    </d:prop>
</d:propfind>

Ici on demande les propriétés displayname, getcontentlength, creationdate, getlastmodified, ishidden, et iscollection.

Description des propriétés :

displayname

Nom affiché

getcontentlength

Taille du corps de message

creationdate

Date de création

getlastmodified

Date de la dernière mise à jour

Ishidden

Attribut fichier caché

iscollection

Dossier si vrai, sinon fichier


L'envoi du corps de message permet de filtrer les propriétés à recevoir et réduire ainsi le trafic. Dans le cas d'une requête PROPFIND sans corps de message, toutes les propriétés disponibles sont reçues.

Voyons maintenant l'implémentation de la méthode PROPFIND au niveau de la requête.

Code C# sans corps de message :

Code C#
Sélectionnez
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(href);
        req.Method = "PROPFIND"; // method WebDAV
    
        // s'authentifie
        if (!String.IsNullOrEmpty(sUserName))
        {
            NetworkCredential networkCredential = new NetworkCredential(sUserName, sPassword);
            req.Credentials = networkCredential;
        }    
        req.ContentType = "text/xml"; // donnée du corps de message en xml
        RequestStream = req.GetRequestStream();
        RequestStream.Close();
        HttpWebResponse webResp = (HttpWebResponse)req.GetResponse();

Après réception de la requête HTTP, le serveur IIS nous transmet les propriétés de la ressource sous la forme XML (voir ci-dessous).

Flux XML retourné par le serveur avec toutes les propriétés disponibles
Sélectionnez
<?xml version="1.0"?>
<a:multistatus xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" xmlns:c="xml:" xmlns:a="DAV:">
  <a:response>
    <a:href>https://test.spie.com/sfr/Log-2008729113352.txt</a:href>
    <a:propstat>
      <a:status>HTTP/1.1 200 OK</a:status>
      <a:prop>
        <a:getcontentlength b:dt="int">0</a:getcontentlength>
        <a:creationdate b:dt="dateTime.tz">2008-08-20T09:44:04.690Z</a:creationdate>
        <a:displayname>Log-2008729113352.txt</a:displayname>
        <a:getlastmodified b:dt="dateTime.rfc1123">Wed, 20 Aug 2008 09:44:04 GMT</a:getlastmodified>
        <a:resourcetype/>
        <a:supportedlock>
          <a:lockentry>
            <a:write/>
            <a:shared/>
          </a:lockentry>
          <a:lockentry>
            <a:write/>
            <a:exclusive/>
          </a:lockentry>
        </a:supportedlock>
        <a:ishidden b:dt="boolean">0</a:ishidden>
        <a:iscollection b:dt="boolean">0</a:iscollection>
        <a:getcontenttype/>
      </a:prop>
    </a:propstat>
  </a:response>
</a:multistatus>
III-A-8-a. Librairies XML

La lecture de flux XML peut se faire grâce au namespace System.XML fourni par la Framework.

Code C#
Sélectionnez
        xmlDoc = new XmlDocument();
        xmlDoc.Load(ResponseStream);
    
        XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable);
        manager.AddNamespace("wd", "DAV:");

Dans tous les cas, on utilise XPath comme langage de sélection de nœuds. Pour la navigation dans les nœuds, on doit spécifier un alias et un namespace de correspondance. L'alias et le namespace mappé, le requêtage XPath pourra fonctionner. Dans notre cas l'alias est 'wd' ; les requêtes se feront sous la forme « /wd:NomDuNœudPrincipal/wd:NomDuNœudEnfant ».

  • Sous VBScript, on définit la propriété avec « SelectionNamespaces » sous la forme xmlns:wd='DAV:'. 'wd' est l'alias et 'DAV:' le namespace à utiliser.
  • Sous Dotnet, on utilise la classe XmlNamespaceManager qui mappe le namespace «DAV:» sous l'alias 'wd'.


À présent, implémentons la fonction de récupération GetProps avec le filtrage des propriétés.

Code C#
Sélectionnez
    /// <summary>
    /// Obtient les propriétés d'une ressource.
    /// </summary>
    /// <param name="href">Lien vers la ressource dont les propriétés sont demandées</param>
    /// <param name="sUserName">Identifiant</param>
    /// <param name="sPassword">Mot de passe</param>
    public void GetProps(string href, string sUserName, string sPassword)
    {
        Stream RequestStream;
        Stream ResponseStream;
        XmlDocument xmlDoc = null;
    
        // flux xml avec les propriétés à récupérer
        string strBody = "<?xml version=\"1.0\"?>"
                + "<d:propfind xmlns:d='DAV:'><d:prop><d:displayname/>
                <d:getcontentlength /><d:creationdate /><d:getlastmodified />
                <d:ishidden /><d:iscollection />
                </d:prop></d:propfind>";
    
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(href);
        req.Method = "PROPFIND"; // method WebDAV
    
        // s'authentifie
        if (!String.IsNullOrEmpty(sUserName))
        {
            NetworkCredential networkCredential = new NetworkCredential(sUserName, sPassword);
            req.Credentials = networkCredential;
        }
    
        // encode en UTF8 le corps de message à transmettre
        byte[] bytes = Encoding.UTF8.GetBytes((string)strBody);
    
        req.ContentType = "text/xml"; // donnée du corps de message en xml
        req.ContentLength = bytes.LongLength; // taille des données du corps de message
    
        RequestStream = req.GetRequestStream();
        RequestStream.Write(bytes, 0, bytes.Length);
        RequestStream.Close();
    
        HttpWebResponse webResp = (HttpWebResponse)req.GetResponse();
    
        // Note : code 207 propre a WebDAV non gérée par HttpStatusCode
        if (((int)webResp.StatusCode) == 207)
        {
            // obtient les propriétés sous la forme d'un flux xml dans la réponse
            ResponseStream = webResp.GetResponseStream();
    
            // traitement du flux xml
            xmlDoc = new XmlDocument();
            xmlDoc.Load(ResponseStream);
    
            // définition alias a pour XPath
            XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable);
            manager.AddNamespace("wd", "DAV:");
    
            XmlNode Conf = xmlDoc.SelectSingleNode("/wd:multistatus/wd:response", manager);
    
            String defhref = Conf.SelectSingleNode("wd:href", manager).InnerText;
    
            XmlNode propConf = Conf.SelectSingleNode("wd:propstat/wd:prop", manager);
            string displayName = propConf.SelectSingleNode("wd:displayname", manager).InnerText;
            string fileLength = propConf.SelectSingleNode("wd:getcontentlength", manager).InnerText;
            string creationDate = propConf.SelectSingleNode("wd:creationdate", manager).InnerText;
            string lastmodified = propConf.SelectSingleNode("wd:getlastmodified", manager).InnerText;
            string isHidden = propConf.SelectSingleNode("wd:ishidden", manager).InnerText;
            string isFolder = propConf.SelectSingleNode("wd:iscollection", manager).InnerText;
    
            Console.WriteLine("propriété de " + href);
            Console.WriteLine("displayName " + displayName);
            Console.WriteLine("fileLength " + fileLength);
            Console.WriteLine("creationDate " + creationDate);
            Console.WriteLine("lastmodified " + lastmodified);
            Console.WriteLine("isHidden " + isHidden);
            Console.WriteLine("isCollection " + isFolder);
    
            ResponseStream.Close();
        }
        webResp.Close();
    }

III-A-9. La suppression d'une ressource distante

La suppression se fait avec la méthode DELETE. La ressource à supprimer est spécifiée directement dans l'url cible de la requête HTTP. La fonction marche aussi bien avec un dossier ; ex. : « http://site/mondossier/ », qu'un fichier « http://site/mondossier/fichier.txt ».

Le serveur renvoie le code réponse 200 (OK) lorsque le fichier est supprimé.

Code C#
Sélectionnez
public HttpStatusCode DeleteResourceWebDAV(string Url, string sUser, string sPassword)
{
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
    req.Method = "DELETE";

    // s'authentifie
    if (!String.IsNullOrEmpty(sUser))
    {
        NetworkCredential networkCredential = new NetworkCredential(sUser, sPassword);
        req.Credentials = networkCredential;
    }

    HttpWebResponse webResp = (HttpWebResponse)req.GetResponse();

    if (webResp.StatusCode == HttpStatusCode.OK)
        Console.WriteLine("Fichier supprimé");
    else
        Console.WriteLine("Echec lors de la suppression. Status " + webResp.StatusCode.ToString() + ", " 
        + webResp.StatusDescription);

    webResp.Close();

    return webResp.StatusCode;
}

IV. Conclusion

Au cours de cet article, nous avons vu comment implémenter des opérations WebDAV en C# avec les technologies .NET.

Grâce à ces langages et aux technologies d'accès aux données comme la Framework .NET, on peut piloter le protocole WebDAV simplement. Par rapport à FTP, le protocole WEBDAV est à privilégier pour son niveau de sécurité et son faible coût de mise en place.

V. Téléchargements

Retrouver le code source de l'article :

Source (6ko) Miroir

VI. Remerciements

Je tiens à remercier Louis-Guillaume MORAND, bbli et toute l'équipe de Developpez.com pour leur soutien et toutes les corrections effectuées.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2008 Dung-Tri LÊ. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.