Sharepoint Office365 sur Linux (Webdav/Davfs) avec des fichiers accentués

Suite de l'aventure avec Sharepoint !

Je me suis rendu compte que les répertoires et les fichiers nommés avec des accents ne sont pas montés par Davfs. Le problème vient bien sur de Microsoft qui n'est pas foutu d'implémenter un protocole en suivant les standards ! Le support technique est une vraie plaie et ne veut pas comprendre que le problème vient de chez eux…

En effet, les spécifications WebDAV indiquent que les caractères spéciaux (espace compris) doivent être encodés en %XXX. Par exemple, on doit retrouver %C3%A9 à la place de é. Or, Sharepoint ne remplace que les espaces (%20). Voici une partie de la réponse HTTP formée par Sharepoint pour un fichier nommé "éducation.pdf" :

<D:href>https://foo.sharepoint.com/sites/bar/Documents%20partages/éducation.pdf</D:href>

Alors que ça devrait être sous cette forme :

<D:href>https://foo.sharepoint.com/sites/bar/Documents%20partages/%C3%A9ducation.pdf</D:href>

Du coup, j'ai du travaillé sur un correctif et voici une POC qui corrige le problème. Elle consiste à faire passer les requêtes HTTP de DavFS à travers un proxy qui fera le boulot de Sharepoint : encoder les caractères en question !

Je travaille sur ma machine de dev dans ~/www/repo/sharepoint-webdav-proxy.

J'ai choisi le proxy mitmproxy car on peut modifier les requêtes et les réponses à la volé.

Les binaires de mitmproxy sont placés dans ./bin/. Si vous lancez une première fois bin/mitmproxy, des certificats SSL seront créés dans ~/.mitmproxy/.

Configuration de DavFS :

$ sudo cp ~simon/.mitmproxy/mitmproxy-ca-cert.pem /etc/davfs2/certs/

Dans /etc/davfs2/davfs2.conf, j'ai ajouté :

[/mnt/sharepoint/]
proxy 127.0.0.1:8118
trust_ca_cert /etc/davfs2/certs/mitmproxy-ca-cert.pem
use_proxy 1
[...]

Adapteur WebDAV :

Dans src/webdav-adapter.py :

import mitmproxy.addonmanager
import mitmproxy.http
import re

class WebdavAdapter:
    def response(self, flow: mitmproxy.http.HTTPFlow):
        data = flow.response.text
        urls = re.findall('(https?[^<\'"]+)', data)

        sorted(urls, key=len)

        for url in reversed(urls):
            data = data.replace(url, self.fixAccents(url))

        flow.response.text = data

    def fixAccents(self, data):
        data = data.replace('\xc3\xb4', '%C3%B4') # ô
        data = data.replace('\xc3\x94', '%C3%94') # Ô
        data = data.replace('\xc3\xa0', '%C3%A0') # à
        data = data.replace('\xc3\x80', '%C3%80') # À
        data = data.replace('\xc3\xa2', '%C3%A2') # â
        data = data.replace('\xc3\x82', '%C3%82') # Â
        data = data.replace('\xc3\xa4', '%C3%A4') # ä
        data = data.replace('\xc3\x84', '%C3%84') # Ä
        data = data.replace('\xc3\xa9', '%C3%A9') # é
        data = data.replace('\xc3\x89', '%C3%89') # É
        data = data.replace('\xc3\xa8', '%C3%A8') # è
        data = data.replace('\xc3\x88', '%C3%88') # È
        data = data.replace('\xc3\xaa', '%C3%AA') # ê
        data = data.replace('\xc3\x8a', '%C3%8A') # Ê
        data = data.replace('\xc3\xab', '%C3%AB') # ë
        data = data.replace('\xc3\x8b', '%C3%8B') # Ë
        data = data.replace('\xc3\xaf', '%C3%AF') # ï
        data = data.replace('\xc3\x8f', '%C3%8F') # Ï
        data = data.replace('\xc3\xae', '%C3%AE') # î
        data = data.replace('\xc3\x8e', '%C3%8E') # Î
        data = data.replace('\xc3\xb4', '%C3%B4') # ô
        data = data.replace('\xc3\x94', '%C3%94') # Ô
        data = data.replace('\xc3\xb6', '%C3%B6') # ö
        data = data.replace('\xc3\x96', '%C3%96') # Ö
        data = data.replace('\xc3\xb9', '%C3%B9') # ù
        data = data.replace('\xc3\x99', '%C3%99') # Ù
        data = data.replace('\xc3\xbb', '%C3%BB') # û
        data = data.replace('\xc3\x9b', '%C3%9B') # Û
        data = data.replace('\xc3\xbc', '%C3%BC') # ü
        data = data.replace('\xc3\x9c', '%C3%9C') # Ü
        data = data.replace('\xc3\xbf', '%C3%BF') # ÿ
        data = data.replace('\xc5\xb8', '%C5%B8') # Ÿ
        data = data.replace('\xc3\xa7', '%C3%A7') # ç
        data = data.replace('\xc3\x87', '%C3%87') # Ç

        return data

addons = [
    WebdavAdapter()
]

Lancement du proxy :

./bin/mitmdump --mode regular --listen-host 127.0.0.1 --listen-port 8118 -s ./src/webdav-adapter.py

Une fois tout ça réalisé, mount.davfs va pouvoir monter les répertoires/fichiers accentués.

Simon Vieille

Sharepoint Office365 sur Linux : automatiser l'authentification (v2)

Sharepoint Office365 sur Linux : automatiser l'authentification (v2)

En septembre 2018, je publiais un article pour automatiser l'authentification sur Sharepoint…

Sharepoint Office365 sur Linux : automatiser l'authentification

Sharepoint Office365 sur Linux : automatiser l'authentification

Suite de l'aventure avec Sharepoint ! On a pu passer 2 étapes cruciales pour jouer avec Sha…

Monter un partage Sharepoint Office365 sur Linux (Webdav/Davfs)

Monter un partage Sharepoint Office365 sur Linux (Webdav/Davfs)

Dans le cadre de mon travail, je développe une application web (nommée Tools) qui fait offic…


  • bmd
  • Salut,
    Super articles. grâce à toi j'accède à mon sharepoint depuis Linux, et maintenant avec les accents.
    J'avais constaté ce problème mais pas trouvé de solution.

    Par contre, petite coquille dans ton script python.
    Les lignes :
    data.replace('\xc3\xa9', 'é') # é
    devraient plutôt être :
    data.replace('\xc3\xa9', '%c3%a9') # é
    Sans ça, ça ne marchait pas (et n'était pas cohérent avec ton explication).

    Pour aller plus loin, j'ai récupéré une liste des caractères et j'ai enrichi ton script à partir de cette page :
    http://i18nqa.com/debug/utf8-debug.html

    Enfin, il me reste un dernier souci : je n'arrive qu'à lire le montage, je n'arrive pas à y écrire.
    Évidemment je monte le filesystem en écriture.
    J'ai ce message avec mitmproxy :
    LOCK https://xxxx.sharepoint.com/personal/xxxx/Documents/test.txt
    << 403 FORBIDDEN 13b
  • bmd
  • Je me réponds...
    En fait, en affichage "raw" ton script est bon. C'est l'affichage enrichi qui transforme les codes utf8 à l'écran !
  • Simon
  • Merci pour ton commentaire !

    Je me suis ouvert une issue pour le problème de rendu d'accent, je n'avais pas fait attention du tout.

    Concernant l'erreur 403, test avec ce paramètre : `use_locks 0`
    Ensuite, test à nouveau en remontant ton espace.

    Ton retour à ce sujet m'intéresse beaucoup !
  • bmd
  • Yes, ça fonctionne avec l'option "use_locks 0". Nickel.
    Y compris la création de fichiers accentués.
    J'ai testé :
    vi /media/sharepoint/test.txt
    vi /media/sharepoint/test\ accentué.txt

    Mitmproxy indique :
    PUT https://xxx.sharepoint.com/personal/xxx/Documents/test.txt
    << 201 CREATED 0b
    PUT https://xxx.sharepoint.com/personal/xxx/Documents/test%20accentu%c3%a9.txt
    << 201 CREATED 0b

    Et je vois bien mes fichiers sur sharepoint.
    Je me demandais ce que ça allait donner, si on allait pas devoir refaire la conversion inverse des accents, mais ce n'est pas utile.

    Ah, et pour info. Le cookie que j'avais créé lors de ton premier article a expiré (hier ou avant-hier je crois), j'ai du le modifier. J'ai fait ça un peu vite, mais il me semble que seul le cookie rtFa avait changé.
    A prendre avec des pincettes...

    Encore merci à toi.
  • bmd
  • Attention, ton script transforme les caractères spéciaux, y compris dans le contenu des fichiers excel (par exemple).
    D'une manière générale, la conversion ne se limite pas au listage des fichiers, mais aussi à leur contenu !!!

Ajouter un commentaire

Votre commentaire - Vous pouvez utiliser du markdown

Renouveler