プロジェクト

全般

プロフィール

Nextcloud9 以降でWebDAVが利用できないバグの対処

Nextcloud/ownCloudはともにSabreDAVというサードパーティのWebDAVサーバをバンドルして
WebDAVを提供しているが、なぜかNextcloudだけ下記のようにWebDAVが安定していなかった。

  • PCクライアントの同期はWebDAV経由だが正常に動作する
  • CarotDAVではファイルは取得できるがファイル一覧では404エラー扱い
  • iOSのGoodReaderではファイルは取得できる
  • それ以外のiOSの多くのWebDAVクライアントではログインはできるがファイルが見えない

環境の調査

共に調査時最新版のNextcloud12とownCloud10のSabreDAVのバージョンとパスは下記である。

  • Nextcloud
    • SabreDAVのパス
      nextcloud/3rdparty/sabre/dav/lib/DAV
      
    • バージョン
      nextcloud/3rdparty/sabre/dav/lib/DAV/Version.php
      -----------------------------
      <?php
      
      namespace Sabre\DAV;
      
      /**
       * This class contains the SabreDAV version constants.
       *
       * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
       * @author Evert Pot (http://evertpot.com/)
       * @license http://sabre.io/license/ Modified BSD License
       */
      class Version {
      
          /**
           * Full version number
           */
          const VERSION = '3.2.2';
      
      }
      
  • ownCloud
    • SabreDAVのパス
      owncloud/lib/composer/sabre/dav/lib/DAV/
      
    • バージョン
      owncloud/lib/composer/sabre/dav/lib/DAV/Version.php
      -----------------------------
      <?php
      
      namespace Sabre\DAV;
      
      /**
       * This class contains the SabreDAV version constants.
       *
       * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
       * @author Evert Pot (http://evertpot.com/)
       * @license http://sabre.io/license/ Modified BSD License
       */
      class Version {
      
          /**
           * Full version number
           */
          const VERSION = '3.2.2';
      
      }
      

どちらも同じ「3.2.2」のようである。

内容の違い

DAV以下の内容でownCloudとNextcloudでdiffを行うと、次の内容が異なる。

# diff -r DAV\(own\) DAV\(next\)
diff -r DAV(own)/Server.php DAV(next)/Server.php
895a896,898
>         $propertyNames = $propFind->getRequestedProperties();
>         $propFindType = !empty($propertyNames) ? PropFind::NORMAL : PropFind::ALLPROPS;
>
897,898d899
<             $subPropFind = clone $propFind;
<             $subPropFind->setDepth($newDepth);
904c905
<             $subPropFind->setPath($subPath);
---
>             $subPropFind = new PropFind($subPath, $propertyNames, $newDepth, $propFindType);

処理の内容が具体的にどう違うかはぱっと見読み取れないような内容であるが、
ループさせてパスなどを参照しているように見える。

ではSabreDAVのオフィシャルから取得した同バージョンのソースとの比較だとどうかというと……
https://github.com/sabre-io/dav/releases

# diff -r DAV\(orig\) DAV\(next\)
diff -r DAV(orig)/Server.php DAV(next)/Server.php
895a896,898
>         $propertyNames = $propFind->getRequestedProperties();
>         $propFindType = !empty($propertyNames) ? PropFind::NORMAL : PropFind::ALLPROPS;
>
897,898d899
<             $subPropFind = clone $propFind;
<             $subPropFind->setDepth($newDepth);
904c905
<             $subPropFind->setPath($subPath);
---
>             $subPropFind = new PropFind($subPath, $propertyNames, $newDepth, $propFindType);

先ほどと同様の内容となる。
つまり、NextCloudの「DAV/Server.php」で行われたと思われる修正に問題がある。

解決策

方針として、オリジナルのServer.phpとNextcloudのServer.phpを差し替える。

  • NextcloudのServer.xmlをバックアップする
    # cd nextcloud/3rdparty/sabre/dav/lib/DAV/
    # mv Server.php old_Server.php
    
  • オリジナルのSabreDAVを取得し、Server.phpをNextcloudのSabreDAVにコピーする。
    # cd ~/
    # wget https://github.com/sabre-io/dav/releases/download/3.2.2/sabredav-3.2.2.zip
    # unzip sabredav-3.2.2.zip
    # cp SabreDAV/vendor/sabre/dav/lib/DAV/Server.php /usr/local/nextcloud/3rdparty/sabre/dav/lib/DAV
    # chown apache.apache /usr/local/nextcloud/3rdparty/sabre/dav/lib/DAV/Server.php
    
  • サービスの再起動は不要なので、ブラウザをリロードあるいはWebDAVアクセスすれば解決する

補足

  • なお公式で修正が行われるまで、本手順はアップグレード時に戻ってしまうため注意