11888: increase announced own cloud server version
[tine20] / tine20 / Tinebase / WebDav / Plugin / OwnCloud.php
1 <?php
2 /**
3  * Tine 2.0
4  *
5  * @package     Tinebase
6  * @subpackage  WebDAV
7  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
8  * @author      Lars Kneschke <l.kneschke@metaways.de>
9  * @copyright   Copyright (c) 2013-2017 Metaways Infosystems GmbH (http://www.metaways.de)
10  *
11  */
12
13 /**
14  * ownCloud Integrator plugin
15  *
16  * This plugin provides functionality reuqired by ownCloud sync clients
17  *
18  * @package     Tinebase
19  * @subpackage  WebDAV
20  */
21 class Tinebase_WebDav_Plugin_OwnCloud extends Sabre\DAV\ServerPlugin
22 {
23
24     const NS_OWNCLOUD = 'http://owncloud.org/ns';
25
26     /**
27      * Min version of owncloud
28      */
29     const OWNCLOUD_MIN_VERSION = '2.0.0';
30
31     /**
32      * Max version of owncloud
33      *
34      * Adjust max version of supported owncloud clients for tine
35      */
36     const OWNCLOUD_MAX_VERSION = '100.0.0';
37
38     /**
39      * Reference to server object
40      *
41      * @var Sabre\DAV\Server
42      */
43     private $server;
44
45     /**
46      * Initializes the plugin
47      *
48      * @param Sabre\DAV\Server $server
49      * @return void
50      */
51     public function initialize(Sabre\DAV\Server $server)
52     {
53         $this->server = $server;
54
55         $server->subscribeEvent('beforeGetProperties', array($this, 'beforeGetProperties'));
56
57         /* Namespaces */
58         $server->xmlNamespaces[self::NS_OWNCLOUD] = 'owncloud';
59
60         array_push($server->protectedProperties,
61             '{' . self::NS_OWNCLOUD . '}id'
62         );
63     }
64
65     /**
66      * Adds ownCloud specific properties
67      *
68      * @param string $path
69      * @param \Sabre\DAV\INode $node
70      * @param array $requestedProperties
71      * @param array $returnedProperties
72      * @return void
73      * @throws \InvalidArgumentException
74      */
75     public function beforeGetProperties(
76         $path,
77         Sabre\DAV\INode $node,
78         array &$requestedProperties,
79         array &$returnedProperties
80     ) {
81         $version = $this->getOwnCloudVersion();
82         if ($version !== null && !$this->isValidOwnCloudVersion()) {
83             $message = sprintf(
84                 '%s::%s OwnCloud client min version is "%s"!',
85                 __METHOD__,
86                 __LINE__,
87                 static::OWNCLOUD_MIN_VERSION
88             );
89
90             Tinebase_Core::getLogger()->debug($message);
91             throw new InvalidArgumentException($message);
92         } elseif (!$version) {
93             // If it's not even an owncloud version, don't add any owncloud specific features here.
94             return;
95         }
96
97         $id = '{' . self::NS_OWNCLOUD . '}id';
98
99         if (in_array($id, $requestedProperties)) {
100             unset($requestedProperties[array_search($id, $requestedProperties)]);
101             if ($node instanceof Tinebase_Frontend_WebDAV_Node) {
102                 $returnedProperties[200][$id] = $node->getId();
103             } else {
104                 // the path does not change for the other nodes => hence the id is "static"
105                 $returnedProperties[200][$id] = sha1($path);
106             }
107         }
108     }
109
110     /**
111      * Return the actuall owncloud version number
112      * @throws \InvalidArgumentException
113      */
114     protected function isValidOwnCloudVersion()
115     {
116         $version  = $this->getOwnCloudVersion();
117
118         return version_compare($version, static::OWNCLOUD_MIN_VERSION, 'ge')
119             && version_compare($version, static::OWNCLOUD_MAX_VERSION, 'le');
120     }
121
122     /**
123      * Get owncloud version number
124      *
125      * @return mixed|null
126      */
127     protected function getOwnCloudVersion() {
128         // Mozilla/5.0 (Macintosh) mirall/2.2.4 (build 3709)
129         /* @var $request \Zend\Http\PhpEnvironment\Request */
130         $request = Tinebase_Core::get(Tinebase_Core::REQUEST);
131
132         // In some cases this is called not out of an request, for example some tests, therefore we should require it here
133         // If it's not an owncloud server, we don't need to determine the version!
134         if (!$request) {
135             return null;
136         }
137
138         $useragentHeader = $request->getHeader('useragent');
139
140         $useragent = $useragentHeader ? $useragentHeader->getFieldValue() : null;
141
142         // If no valid header, this is not an owncloud client
143         if ($useragent === null) {
144             return null;
145         }
146
147         $match = [];
148
149         if (!preg_match('/mirall\/(\d\.\d\.\d)/', $useragent, $match)) {
150             return null;
151         }
152
153         $version = array_pop($match);
154
155         if ($version === '') {
156             $version = null;
157         }
158
159         return $version;
160     }
161 }