Completed
Push — developer ( d751a3...e1a3df )
by Błażej
164:44 queued 111:37
created
libraries/SabreDAV/DAV/Mount/Plugin.php 1 patch
Indentation   +64 added lines, -64 removed lines patch added patch discarded remove patch
@@ -17,70 +17,70 @@
 block discarded – undo
17 17
  */
18 18
 class Plugin extends DAV\ServerPlugin {
19 19
 
20
-    /**
21
-     * Reference to Server class
22
-     *
23
-     * @var Sabre\DAV\Server
24
-     */
25
-    protected $server;
26
-
27
-    /**
28
-     * Initializes the plugin and registers event handles
29
-     *
30
-     * @param DAV\Server $server
31
-     * @return void
32
-     */
33
-    public function initialize(DAV\Server $server) {
34
-
35
-        $this->server = $server;
36
-        $this->server->on('method:GET', [$this, 'httpGet'], 90);
37
-
38
-    }
39
-
40
-    /**
41
-     * 'beforeMethod' event handles. This event handles intercepts GET requests ending
42
-     * with ?mount
43
-     *
44
-     * @param RequestInterface $request
45
-     * @param ResponseInterface $response
46
-     * @return bool
47
-     */
48
-    public function httpGet(RequestInterface $request, ResponseInterface $response) {
49
-
50
-        $queryParams = $request->getQueryParameters();
51
-        if (!array_key_exists('mount', $queryParams)) return;
52
-
53
-        $currentUri = $request->getAbsoluteUrl();
54
-
55
-        // Stripping off everything after the ?
56
-        list($currentUri) = explode('?', $currentUri);
57
-
58
-        $this->davMount($response, $currentUri);
59
-
60
-        // Returning false to break the event chain
61
-        return false;
62
-
63
-    }
64
-
65
-    /**
66
-     * Generates the davmount response
67
-     *
68
-     * @param ResponseInterface $response
69
-     * @param string $uri absolute uri
70
-     * @return void
71
-     */
72
-    public function davMount(ResponseInterface $response, $uri) {
73
-
74
-        $response->setStatus(200);
75
-        $response->setHeader('Content-Type', 'application/davmount+xml');
76
-        ob_start();
77
-        echo '<?xml version="1.0"?>', "\n";
78
-        echo "<dm:mount xmlns:dm=\"http://purl.org/NET/webdav/mount\">\n";
79
-        echo "  <dm:url>", htmlspecialchars($uri, ENT_NOQUOTES, 'UTF-8'), "</dm:url>\n";
80
-        echo "</dm:mount>";
81
-        $response->setBody(ob_get_clean());
82
-
83
-    }
20
+	/**
21
+	 * Reference to Server class
22
+	 *
23
+	 * @var Sabre\DAV\Server
24
+	 */
25
+	protected $server;
26
+
27
+	/**
28
+	 * Initializes the plugin and registers event handles
29
+	 *
30
+	 * @param DAV\Server $server
31
+	 * @return void
32
+	 */
33
+	public function initialize(DAV\Server $server) {
34
+
35
+		$this->server = $server;
36
+		$this->server->on('method:GET', [$this, 'httpGet'], 90);
37
+
38
+	}
39
+
40
+	/**
41
+	 * 'beforeMethod' event handles. This event handles intercepts GET requests ending
42
+	 * with ?mount
43
+	 *
44
+	 * @param RequestInterface $request
45
+	 * @param ResponseInterface $response
46
+	 * @return bool
47
+	 */
48
+	public function httpGet(RequestInterface $request, ResponseInterface $response) {
49
+
50
+		$queryParams = $request->getQueryParameters();
51
+		if (!array_key_exists('mount', $queryParams)) return;
52
+
53
+		$currentUri = $request->getAbsoluteUrl();
54
+
55
+		// Stripping off everything after the ?
56
+		list($currentUri) = explode('?', $currentUri);
57
+
58
+		$this->davMount($response, $currentUri);
59
+
60
+		// Returning false to break the event chain
61
+		return false;
62
+
63
+	}
64
+
65
+	/**
66
+	 * Generates the davmount response
67
+	 *
68
+	 * @param ResponseInterface $response
69
+	 * @param string $uri absolute uri
70
+	 * @return void
71
+	 */
72
+	public function davMount(ResponseInterface $response, $uri) {
73
+
74
+		$response->setStatus(200);
75
+		$response->setHeader('Content-Type', 'application/davmount+xml');
76
+		ob_start();
77
+		echo '<?xml version="1.0"?>', "\n";
78
+		echo "<dm:mount xmlns:dm=\"http://purl.org/NET/webdav/mount\">\n";
79
+		echo "  <dm:url>", htmlspecialchars($uri, ENT_NOQUOTES, 'UTF-8'), "</dm:url>\n";
80
+		echo "</dm:mount>";
81
+		$response->setBody(ob_get_clean());
82
+
83
+	}
84 84
 
85 85
 
86 86
 }
Please login to merge, or discard this patch.
libraries/SabreDAV/DAV/Sync/ISyncCollection.php 1 patch
Indentation   +66 added lines, -66 removed lines patch added patch discarded remove patch
@@ -17,72 +17,72 @@
 block discarded – undo
17 17
  */
18 18
 interface ISyncCollection extends DAV\ICollection {
19 19
 
20
-    /**
21
-     * This method returns the current sync-token for this collection.
22
-     * This can be any string.
23
-     *
24
-     * If null is returned from this function, the plugin assumes there's no
25
-     * sync information available.
26
-     *
27
-     * @return string|null
28
-     */
29
-    public function getSyncToken();
20
+	/**
21
+	 * This method returns the current sync-token for this collection.
22
+	 * This can be any string.
23
+	 *
24
+	 * If null is returned from this function, the plugin assumes there's no
25
+	 * sync information available.
26
+	 *
27
+	 * @return string|null
28
+	 */
29
+	public function getSyncToken();
30 30
 
31
-    /**
32
-     * The getChanges method returns all the changes that have happened, since
33
-     * the specified syncToken and the current collection.
34
-     *
35
-     * This function should return an array, such as the following:
36
-     *
37
-     * [
38
-     *   'syncToken' => 'The current synctoken',
39
-     *   'added'   => [
40
-     *      'new.txt',
41
-     *   ],
42
-     *   'modified'   => [
43
-     *      'modified.txt',
44
-     *   ],
45
-     *   'deleted' => array(
46
-     *      'foo.php.bak',
47
-     *      'old.txt'
48
-     *   )
49
-     * ];
50
-     *
51
-     * The syncToken property should reflect the *current* syncToken of the
52
-     * collection, as reported getSyncToken(). This is needed here too, to
53
-     * ensure the operation is atomic.
54
-     *
55
-     * If the syncToken is specified as null, this is an initial sync, and all
56
-     * members should be reported.
57
-     *
58
-     * The modified property is an array of nodenames that have changed since
59
-     * the last token.
60
-     *
61
-     * The deleted property is an array with nodenames, that have been deleted
62
-     * from collection.
63
-     *
64
-     * The second argument is basically the 'depth' of the report. If it's 1,
65
-     * you only have to report changes that happened only directly in immediate
66
-     * descendants. If it's 2, it should also include changes from the nodes
67
-     * below the child collections. (grandchildren)
68
-     *
69
-     * The third (optional) argument allows a client to specify how many
70
-     * results should be returned at most. If the limit is not specified, it
71
-     * should be treated as infinite.
72
-     *
73
-     * If the limit (infinite or not) is higher than you're willing to return,
74
-     * you should throw a Sabre\DAV\Exception\TooMuchMatches() exception.
75
-     *
76
-     * If the syncToken is expired (due to data cleanup) or unknown, you must
77
-     * return null.
78
-     *
79
-     * The limit is 'suggestive'. You are free to ignore it.
80
-     *
81
-     * @param string $syncToken
82
-     * @param int $syncLevel
83
-     * @param int $limit
84
-     * @return array
85
-     */
86
-    public function getChanges($syncToken, $syncLevel, $limit = null);
31
+	/**
32
+	 * The getChanges method returns all the changes that have happened, since
33
+	 * the specified syncToken and the current collection.
34
+	 *
35
+	 * This function should return an array, such as the following:
36
+	 *
37
+	 * [
38
+	 *   'syncToken' => 'The current synctoken',
39
+	 *   'added'   => [
40
+	 *      'new.txt',
41
+	 *   ],
42
+	 *   'modified'   => [
43
+	 *      'modified.txt',
44
+	 *   ],
45
+	 *   'deleted' => array(
46
+	 *      'foo.php.bak',
47
+	 *      'old.txt'
48
+	 *   )
49
+	 * ];
50
+	 *
51
+	 * The syncToken property should reflect the *current* syncToken of the
52
+	 * collection, as reported getSyncToken(). This is needed here too, to
53
+	 * ensure the operation is atomic.
54
+	 *
55
+	 * If the syncToken is specified as null, this is an initial sync, and all
56
+	 * members should be reported.
57
+	 *
58
+	 * The modified property is an array of nodenames that have changed since
59
+	 * the last token.
60
+	 *
61
+	 * The deleted property is an array with nodenames, that have been deleted
62
+	 * from collection.
63
+	 *
64
+	 * The second argument is basically the 'depth' of the report. If it's 1,
65
+	 * you only have to report changes that happened only directly in immediate
66
+	 * descendants. If it's 2, it should also include changes from the nodes
67
+	 * below the child collections. (grandchildren)
68
+	 *
69
+	 * The third (optional) argument allows a client to specify how many
70
+	 * results should be returned at most. If the limit is not specified, it
71
+	 * should be treated as infinite.
72
+	 *
73
+	 * If the limit (infinite or not) is higher than you're willing to return,
74
+	 * you should throw a Sabre\DAV\Exception\TooMuchMatches() exception.
75
+	 *
76
+	 * If the syncToken is expired (due to data cleanup) or unknown, you must
77
+	 * return null.
78
+	 *
79
+	 * The limit is 'suggestive'. You are free to ignore it.
80
+	 *
81
+	 * @param string $syncToken
82
+	 * @param int $syncLevel
83
+	 * @param int $limit
84
+	 * @return array
85
+	 */
86
+	public function getChanges($syncToken, $syncLevel, $limit = null);
87 87
 
88 88
 }
Please login to merge, or discard this patch.
libraries/SabreDAV/DAV/Sync/Plugin.php 1 patch
Indentation   +253 added lines, -253 removed lines patch added patch discarded remove patch
@@ -20,258 +20,258 @@
 block discarded – undo
20 20
  */
21 21
 class Plugin extends DAV\ServerPlugin {
22 22
 
23
-    /**
24
-     * Reference to server object
25
-     *
26
-     * @var DAV\Server
27
-     */
28
-    protected $server;
29
-
30
-    const SYNCTOKEN_PREFIX = 'http://sabre.io/ns/sync/';
31
-
32
-    /**
33
-     * Returns a plugin name.
34
-     *
35
-     * Using this name other plugins will be able to access other plugins
36
-     * using \Sabre\DAV\Server::getPlugin
37
-     *
38
-     * @return string
39
-     */
40
-    public function getPluginName() {
41
-
42
-        return 'sync';
43
-
44
-    }
45
-
46
-    /**
47
-     * Initializes the plugin.
48
-     *
49
-     * This is when the plugin registers it's hooks.
50
-     *
51
-     * @param DAV\Server $server
52
-     * @return void
53
-     */
54
-    public function initialize(DAV\Server $server) {
55
-
56
-        $this->server = $server;
57
-        $server->xml->elementMap['{DAV:}sync-collection'] = 'Sabre\\DAV\\Xml\\Request\\SyncCollectionReport';
58
-
59
-        $self = $this;
60
-
61
-        $server->on('report', function($reportName, $dom, $uri) use ($self) {
62
-
63
-            if ($reportName === '{DAV:}sync-collection') {
64
-                $this->server->transactionType = 'report-sync-collection';
65
-                $self->syncCollection($uri, $dom);
66
-                return false;
67
-            }
68
-
69
-        });
70
-
71
-        $server->on('propFind',       [$this, 'propFind']);
72
-        $server->on('validateTokens', [$this, 'validateTokens']);
73
-
74
-    }
75
-
76
-    /**
77
-     * Returns a list of reports this plugin supports.
78
-     *
79
-     * This will be used in the {DAV:}supported-report-set property.
80
-     * Note that you still need to subscribe to the 'report' event to actually
81
-     * implement them
82
-     *
83
-     * @param string $uri
84
-     * @return array
85
-     */
86
-    public function getSupportedReportSet($uri) {
87
-
88
-        $node = $this->server->tree->getNodeForPath($uri);
89
-        if ($node instanceof ISyncCollection && $node->getSyncToken()) {
90
-            return [
91
-                '{DAV:}sync-collection',
92
-            ];
93
-        }
94
-
95
-        return [];
96
-
97
-    }
98
-
99
-
100
-    /**
101
-     * This method handles the {DAV:}sync-collection HTTP REPORT.
102
-     *
103
-     * @param string $uri
104
-     * @param SyncCollectionReport $report
105
-     * @return void
106
-     */
107
-    public function syncCollection($uri, SyncCollectionReport $report) {
108
-
109
-        // Getting the data
110
-        $node = $this->server->tree->getNodeForPath($uri);
111
-        if (!$node instanceof ISyncCollection) {
112
-            throw new DAV\Exception\ReportNotSupported('The {DAV:}sync-collection REPORT is not supported on this url.');
113
-        }
114
-        $token = $node->getSyncToken();
115
-        if (!$token) {
116
-            throw new DAV\Exception\ReportNotSupported('No sync information is available at this node');
117
-        }
118
-
119
-        $syncToken = $report->syncToken;
120
-        if (!is_null($syncToken)) {
121
-            // Sync-token must start with our prefix
122
-            if (substr($syncToken, 0, strlen(self::SYNCTOKEN_PREFIX)) !== self::SYNCTOKEN_PREFIX) {
123
-                throw new DAV\Exception\InvalidSyncToken('Invalid or unknown sync token');
124
-            }
125
-
126
-            $syncToken = substr($syncToken, strlen(self::SYNCTOKEN_PREFIX));
127
-
128
-        }
129
-        $changeInfo = $node->getChanges($syncToken, $report->syncLevel, $report->limit);
130
-
131
-        if (is_null($changeInfo)) {
132
-
133
-            throw new DAV\Exception\InvalidSyncToken('Invalid or unknown sync token');
134
-
135
-        }
136
-
137
-        // Encoding the response
138
-        $this->sendSyncCollectionResponse(
139
-            $changeInfo['syncToken'],
140
-            $uri,
141
-            $changeInfo['added'],
142
-            $changeInfo['modified'],
143
-            $changeInfo['deleted'],
144
-            $report->properties
145
-        );
146
-
147
-    }
148
-
149
-    /**
150
-     * Sends the response to a sync-collection request.
151
-     *
152
-     * @param string $syncToken
153
-     * @param string $collectionUrl
154
-     * @param array $added
155
-     * @param array $modified
156
-     * @param array $deleted
157
-     * @param array $properties
158
-     * @return void
159
-     */
160
-    protected function sendSyncCollectionResponse($syncToken, $collectionUrl, array $added, array $modified, array $deleted, array $properties) {
161
-
162
-
163
-        $fullPaths = [];
164
-
165
-        // Pre-fetching children, if this is possible.
166
-        foreach (array_merge($added, $modified) as $item) {
167
-            $fullPath = $collectionUrl . '/' . $item;
168
-            $fullPaths[] = $fullPath;
169
-        }
170
-
171
-        $responses = [];
172
-        foreach ($this->server->getPropertiesForMultiplePaths($fullPaths, $properties) as $fullPath => $props) {
173
-
174
-            // The 'Property_Response' class is responsible for generating a
175
-            // single {DAV:}response xml element.
176
-            $responses[] = new DAV\Xml\Element\Response($fullPath, $props);
177
-
178
-        }
179
-
180
-
181
-
182
-        // Deleted items also show up as 'responses'. They have no properties,
183
-        // and a single {DAV:}status element set as 'HTTP/1.1 404 Not Found'.
184
-        foreach ($deleted as $item) {
185
-
186
-            $fullPath = $collectionUrl . '/' . $item;
187
-            $responses[] = new DAV\Xml\Element\Response($fullPath, [], 404);
188
-
189
-        }
190
-        $multiStatus = new DAV\Xml\Response\MultiStatus($responses, self::SYNCTOKEN_PREFIX . $syncToken);
191
-
192
-        $this->server->httpResponse->setStatus(207);
193
-        $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
194
-        $this->server->httpResponse->setBody(
195
-            $this->server->xml->write('{DAV:}multistatus', $multiStatus, $this->server->getBaseUri())
196
-        );
197
-
198
-    }
199
-
200
-    /**
201
-     * This method is triggered whenever properties are requested for a node.
202
-     * We intercept this to see if we must return a {DAV:}sync-token.
203
-     *
204
-     * @param DAV\PropFind $propFind
205
-     * @param DAV\INode $node
206
-     * @return void
207
-     */
208
-    public function propFind(DAV\PropFind $propFind, DAV\INode $node) {
209
-
210
-        $propFind->handle('{DAV:}sync-token', function() use ($node) {
211
-            if (!$node instanceof ISyncCollection || !$token = $node->getSyncToken()) {
212
-                return;
213
-            }
214
-            return self::SYNCTOKEN_PREFIX . $token;
215
-        });
216
-
217
-    }
218
-
219
-    /**
220
-     * The validateTokens event is triggered before every request.
221
-     *
222
-     * It's a moment where this plugin can check all the supplied lock tokens
223
-     * in the If: header, and check if they are valid.
224
-     *
225
-     * @param RequestInterface $request
226
-     * @param array $conditions
227
-     * @return void
228
-     */
229
-    public function validateTokens(RequestInterface $request, &$conditions) {
230
-
231
-        foreach ($conditions as $kk => $condition) {
232
-
233
-            foreach ($condition['tokens'] as $ii => $token) {
234
-
235
-                // Sync-tokens must always start with our designated prefix.
236
-                if (substr($token['token'], 0, strlen(self::SYNCTOKEN_PREFIX)) !== self::SYNCTOKEN_PREFIX) {
237
-                    continue;
238
-                }
239
-
240
-                // Checking if the token is a match.
241
-                $node = $this->server->tree->getNodeForPath($condition['uri']);
242
-
243
-                if (
244
-                    $node instanceof ISyncCollection &&
245
-                    $node->getSyncToken() == substr($token['token'], strlen(self::SYNCTOKEN_PREFIX))
246
-                ) {
247
-                    $conditions[$kk]['tokens'][$ii]['validToken'] = true;
248
-                }
249
-
250
-            }
251
-
252
-        }
253
-
254
-    }
255
-
256
-    /**
257
-     * Returns a bunch of meta-data about the plugin.
258
-     *
259
-     * Providing this information is optional, and is mainly displayed by the
260
-     * Browser plugin.
261
-     *
262
-     * The description key in the returned array may contain html and will not
263
-     * be sanitized.
264
-     *
265
-     * @return array
266
-     */
267
-    public function getPluginInfo() {
268
-
269
-        return [
270
-            'name'        => $this->getPluginName(),
271
-            'description' => 'Adds support for WebDAV Collection Sync (rfc6578)',
272
-            'link'        => 'http://sabre.io/dav/sync/',
273
-        ];
274
-
275
-    }
23
+	/**
24
+	 * Reference to server object
25
+	 *
26
+	 * @var DAV\Server
27
+	 */
28
+	protected $server;
29
+
30
+	const SYNCTOKEN_PREFIX = 'http://sabre.io/ns/sync/';
31
+
32
+	/**
33
+	 * Returns a plugin name.
34
+	 *
35
+	 * Using this name other plugins will be able to access other plugins
36
+	 * using \Sabre\DAV\Server::getPlugin
37
+	 *
38
+	 * @return string
39
+	 */
40
+	public function getPluginName() {
41
+
42
+		return 'sync';
43
+
44
+	}
45
+
46
+	/**
47
+	 * Initializes the plugin.
48
+	 *
49
+	 * This is when the plugin registers it's hooks.
50
+	 *
51
+	 * @param DAV\Server $server
52
+	 * @return void
53
+	 */
54
+	public function initialize(DAV\Server $server) {
55
+
56
+		$this->server = $server;
57
+		$server->xml->elementMap['{DAV:}sync-collection'] = 'Sabre\\DAV\\Xml\\Request\\SyncCollectionReport';
58
+
59
+		$self = $this;
60
+
61
+		$server->on('report', function($reportName, $dom, $uri) use ($self) {
62
+
63
+			if ($reportName === '{DAV:}sync-collection') {
64
+				$this->server->transactionType = 'report-sync-collection';
65
+				$self->syncCollection($uri, $dom);
66
+				return false;
67
+			}
68
+
69
+		});
70
+
71
+		$server->on('propFind',       [$this, 'propFind']);
72
+		$server->on('validateTokens', [$this, 'validateTokens']);
73
+
74
+	}
75
+
76
+	/**
77
+	 * Returns a list of reports this plugin supports.
78
+	 *
79
+	 * This will be used in the {DAV:}supported-report-set property.
80
+	 * Note that you still need to subscribe to the 'report' event to actually
81
+	 * implement them
82
+	 *
83
+	 * @param string $uri
84
+	 * @return array
85
+	 */
86
+	public function getSupportedReportSet($uri) {
87
+
88
+		$node = $this->server->tree->getNodeForPath($uri);
89
+		if ($node instanceof ISyncCollection && $node->getSyncToken()) {
90
+			return [
91
+				'{DAV:}sync-collection',
92
+			];
93
+		}
94
+
95
+		return [];
96
+
97
+	}
98
+
99
+
100
+	/**
101
+	 * This method handles the {DAV:}sync-collection HTTP REPORT.
102
+	 *
103
+	 * @param string $uri
104
+	 * @param SyncCollectionReport $report
105
+	 * @return void
106
+	 */
107
+	public function syncCollection($uri, SyncCollectionReport $report) {
108
+
109
+		// Getting the data
110
+		$node = $this->server->tree->getNodeForPath($uri);
111
+		if (!$node instanceof ISyncCollection) {
112
+			throw new DAV\Exception\ReportNotSupported('The {DAV:}sync-collection REPORT is not supported on this url.');
113
+		}
114
+		$token = $node->getSyncToken();
115
+		if (!$token) {
116
+			throw new DAV\Exception\ReportNotSupported('No sync information is available at this node');
117
+		}
118
+
119
+		$syncToken = $report->syncToken;
120
+		if (!is_null($syncToken)) {
121
+			// Sync-token must start with our prefix
122
+			if (substr($syncToken, 0, strlen(self::SYNCTOKEN_PREFIX)) !== self::SYNCTOKEN_PREFIX) {
123
+				throw new DAV\Exception\InvalidSyncToken('Invalid or unknown sync token');
124
+			}
125
+
126
+			$syncToken = substr($syncToken, strlen(self::SYNCTOKEN_PREFIX));
127
+
128
+		}
129
+		$changeInfo = $node->getChanges($syncToken, $report->syncLevel, $report->limit);
130
+
131
+		if (is_null($changeInfo)) {
132
+
133
+			throw new DAV\Exception\InvalidSyncToken('Invalid or unknown sync token');
134
+
135
+		}
136
+
137
+		// Encoding the response
138
+		$this->sendSyncCollectionResponse(
139
+			$changeInfo['syncToken'],
140
+			$uri,
141
+			$changeInfo['added'],
142
+			$changeInfo['modified'],
143
+			$changeInfo['deleted'],
144
+			$report->properties
145
+		);
146
+
147
+	}
148
+
149
+	/**
150
+	 * Sends the response to a sync-collection request.
151
+	 *
152
+	 * @param string $syncToken
153
+	 * @param string $collectionUrl
154
+	 * @param array $added
155
+	 * @param array $modified
156
+	 * @param array $deleted
157
+	 * @param array $properties
158
+	 * @return void
159
+	 */
160
+	protected function sendSyncCollectionResponse($syncToken, $collectionUrl, array $added, array $modified, array $deleted, array $properties) {
161
+
162
+
163
+		$fullPaths = [];
164
+
165
+		// Pre-fetching children, if this is possible.
166
+		foreach (array_merge($added, $modified) as $item) {
167
+			$fullPath = $collectionUrl . '/' . $item;
168
+			$fullPaths[] = $fullPath;
169
+		}
170
+
171
+		$responses = [];
172
+		foreach ($this->server->getPropertiesForMultiplePaths($fullPaths, $properties) as $fullPath => $props) {
173
+
174
+			// The 'Property_Response' class is responsible for generating a
175
+			// single {DAV:}response xml element.
176
+			$responses[] = new DAV\Xml\Element\Response($fullPath, $props);
177
+
178
+		}
179
+
180
+
181
+
182
+		// Deleted items also show up as 'responses'. They have no properties,
183
+		// and a single {DAV:}status element set as 'HTTP/1.1 404 Not Found'.
184
+		foreach ($deleted as $item) {
185
+
186
+			$fullPath = $collectionUrl . '/' . $item;
187
+			$responses[] = new DAV\Xml\Element\Response($fullPath, [], 404);
188
+
189
+		}
190
+		$multiStatus = new DAV\Xml\Response\MultiStatus($responses, self::SYNCTOKEN_PREFIX . $syncToken);
191
+
192
+		$this->server->httpResponse->setStatus(207);
193
+		$this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
194
+		$this->server->httpResponse->setBody(
195
+			$this->server->xml->write('{DAV:}multistatus', $multiStatus, $this->server->getBaseUri())
196
+		);
197
+
198
+	}
199
+
200
+	/**
201
+	 * This method is triggered whenever properties are requested for a node.
202
+	 * We intercept this to see if we must return a {DAV:}sync-token.
203
+	 *
204
+	 * @param DAV\PropFind $propFind
205
+	 * @param DAV\INode $node
206
+	 * @return void
207
+	 */
208
+	public function propFind(DAV\PropFind $propFind, DAV\INode $node) {
209
+
210
+		$propFind->handle('{DAV:}sync-token', function() use ($node) {
211
+			if (!$node instanceof ISyncCollection || !$token = $node->getSyncToken()) {
212
+				return;
213
+			}
214
+			return self::SYNCTOKEN_PREFIX . $token;
215
+		});
216
+
217
+	}
218
+
219
+	/**
220
+	 * The validateTokens event is triggered before every request.
221
+	 *
222
+	 * It's a moment where this plugin can check all the supplied lock tokens
223
+	 * in the If: header, and check if they are valid.
224
+	 *
225
+	 * @param RequestInterface $request
226
+	 * @param array $conditions
227
+	 * @return void
228
+	 */
229
+	public function validateTokens(RequestInterface $request, &$conditions) {
230
+
231
+		foreach ($conditions as $kk => $condition) {
232
+
233
+			foreach ($condition['tokens'] as $ii => $token) {
234
+
235
+				// Sync-tokens must always start with our designated prefix.
236
+				if (substr($token['token'], 0, strlen(self::SYNCTOKEN_PREFIX)) !== self::SYNCTOKEN_PREFIX) {
237
+					continue;
238
+				}
239
+
240
+				// Checking if the token is a match.
241
+				$node = $this->server->tree->getNodeForPath($condition['uri']);
242
+
243
+				if (
244
+					$node instanceof ISyncCollection &&
245
+					$node->getSyncToken() == substr($token['token'], strlen(self::SYNCTOKEN_PREFIX))
246
+				) {
247
+					$conditions[$kk]['tokens'][$ii]['validToken'] = true;
248
+				}
249
+
250
+			}
251
+
252
+		}
253
+
254
+	}
255
+
256
+	/**
257
+	 * Returns a bunch of meta-data about the plugin.
258
+	 *
259
+	 * Providing this information is optional, and is mainly displayed by the
260
+	 * Browser plugin.
261
+	 *
262
+	 * The description key in the returned array may contain html and will not
263
+	 * be sanitized.
264
+	 *
265
+	 * @return array
266
+	 */
267
+	public function getPluginInfo() {
268
+
269
+		return [
270
+			'name'        => $this->getPluginName(),
271
+			'description' => 'Adds support for WebDAV Collection Sync (rfc6578)',
272
+			'link'        => 'http://sabre.io/dav/sync/',
273
+		];
274
+
275
+	}
276 276
 
277 277
 }
Please login to merge, or discard this patch.
libraries/SabreDAV/DAV/IExtendedCollection.php 1 patch
Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -14,30 +14,30 @@
 block discarded – undo
14 14
  */
15 15
 interface IExtendedCollection extends ICollection {
16 16
 
17
-    /**
18
-     * Creates a new collection.
19
-     *
20
-     * This method will receive a MkCol object with all the information about
21
-     * the new collection that's being created.
22
-     *
23
-     * The MkCol object contains information about the resourceType of the new
24
-     * collection. If you don't support the specified resourceType, you should
25
-     * throw Exception\InvalidResourceType.
26
-     *
27
-     * The object also contains a list of WebDAV properties for the new
28
-     * collection.
29
-     *
30
-     * You should call the handle() method on this object to specify exactly
31
-     * which properties you are storing. This allows the system to figure out
32
-     * exactly which properties you didn't store, which in turn allows other
33
-     * plugins (such as the propertystorage plugin) to handle storing the
34
-     * property for you.
35
-     *
36
-     * @param string $name
37
-     * @param MkCol $mkCol
38
-     * @throws Exception\InvalidResourceType
39
-     * @return void
40
-     */
41
-    public function createExtendedCollection($name, MkCol $mkCol);
17
+	/**
18
+	 * Creates a new collection.
19
+	 *
20
+	 * This method will receive a MkCol object with all the information about
21
+	 * the new collection that's being created.
22
+	 *
23
+	 * The MkCol object contains information about the resourceType of the new
24
+	 * collection. If you don't support the specified resourceType, you should
25
+	 * throw Exception\InvalidResourceType.
26
+	 *
27
+	 * The object also contains a list of WebDAV properties for the new
28
+	 * collection.
29
+	 *
30
+	 * You should call the handle() method on this object to specify exactly
31
+	 * which properties you are storing. This allows the system to figure out
32
+	 * exactly which properties you didn't store, which in turn allows other
33
+	 * plugins (such as the propertystorage plugin) to handle storing the
34
+	 * property for you.
35
+	 *
36
+	 * @param string $name
37
+	 * @param MkCol $mkCol
38
+	 * @throws Exception\InvalidResourceType
39
+	 * @return void
40
+	 */
41
+	public function createExtendedCollection($name, MkCol $mkCol);
42 42
 
43 43
 }
Please login to merge, or discard this patch.
libraries/SabreDAV/DAV/MkCol.php 1 patch
Indentation   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -22,50 +22,50 @@
 block discarded – undo
22 22
  */
23 23
 class MkCol extends PropPatch {
24 24
 
25
-    /**
26
-     * A list of resource-types in clark-notation.
27
-     *
28
-     * @var array
29
-     */
30
-    protected $resourceType;
25
+	/**
26
+	 * A list of resource-types in clark-notation.
27
+	 *
28
+	 * @var array
29
+	 */
30
+	protected $resourceType;
31 31
 
32
-    /**
33
-     * Creates the MKCOL object.
34
-     *
35
-     * @param string[] $resourceType List of resourcetype values.
36
-     * @param array $mutations List of new properties values.
37
-     */
38
-    public function __construct(array $resourceType, array $mutations) {
32
+	/**
33
+	 * Creates the MKCOL object.
34
+	 *
35
+	 * @param string[] $resourceType List of resourcetype values.
36
+	 * @param array $mutations List of new properties values.
37
+	 */
38
+	public function __construct(array $resourceType, array $mutations) {
39 39
 
40
-        $this->resourceType = $resourceType;
41
-        parent::__construct($mutations);
40
+		$this->resourceType = $resourceType;
41
+		parent::__construct($mutations);
42 42
 
43
-    }
43
+	}
44 44
 
45
-    /**
46
-     * Returns the resourcetype of the new collection.
47
-     *
48
-     * @return string[]
49
-     */
50
-    public function getResourceType() {
45
+	/**
46
+	 * Returns the resourcetype of the new collection.
47
+	 *
48
+	 * @return string[]
49
+	 */
50
+	public function getResourceType() {
51 51
 
52
-        return $this->resourceType;
52
+		return $this->resourceType;
53 53
 
54
-    }
54
+	}
55 55
 
56
-    /**
57
-     * Returns true or false if the MKCOL operation has at least the specified
58
-     * resource type.
59
-     *
60
-     * If the resourcetype is specified as an array, all resourcetypes are
61
-     * checked.
62
-     *
63
-     * @param string|string[] $resourceType
64
-     */
65
-    public function hasResourceType($resourceType) {
56
+	/**
57
+	 * Returns true or false if the MKCOL operation has at least the specified
58
+	 * resource type.
59
+	 *
60
+	 * If the resourcetype is specified as an array, all resourcetypes are
61
+	 * checked.
62
+	 *
63
+	 * @param string|string[] $resourceType
64
+	 */
65
+	public function hasResourceType($resourceType) {
66 66
 
67
-        return count(array_diff((array)$resourceType, $this->resourceType)) === 0;
67
+		return count(array_diff((array)$resourceType, $this->resourceType)) === 0;
68 68
 
69
-    }
69
+	}
70 70
 
71 71
 }
Please login to merge, or discard this patch.
libraries/SabreDAV/DAV/Collection.php 1 patch
Indentation   +90 added lines, -90 removed lines patch added patch discarded remove patch
@@ -14,96 +14,96 @@
 block discarded – undo
14 14
  */
15 15
 abstract class Collection extends Node implements ICollection {
16 16
 
17
-    /**
18
-     * Returns a child object, by its name.
19
-     *
20
-     * This method makes use of the getChildren method to grab all the child
21
-     * nodes, and compares the name.
22
-     * Generally its wise to override this, as this can usually be optimized
23
-     *
24
-     * This method must throw Sabre\DAV\Exception\NotFound if the node does not
25
-     * exist.
26
-     *
27
-     * @param string $name
28
-     * @throws Exception\NotFound
29
-     * @return INode
30
-     */
31
-    public function getChild($name) {
32
-
33
-        foreach ($this->getChildren() as $child) {
34
-
35
-            if ($child->getName() === $name) return $child;
36
-
37
-        }
38
-        throw new Exception\NotFound('File not found: ' . $name);
39
-
40
-    }
41
-
42
-    /**
43
-     * Checks is a child-node exists.
44
-     *
45
-     * It is generally a good idea to try and override this. Usually it can be optimized.
46
-     *
47
-     * @param string $name
48
-     * @return bool
49
-     */
50
-    public function childExists($name) {
51
-
52
-        try {
53
-
54
-            $this->getChild($name);
55
-            return true;
56
-
57
-        } catch (Exception\NotFound $e) {
58
-
59
-            return false;
60
-
61
-        }
62
-
63
-    }
64
-
65
-    /**
66
-     * Creates a new file in the directory
67
-     *
68
-     * Data will either be supplied as a stream resource, or in certain cases
69
-     * as a string. Keep in mind that you may have to support either.
70
-     *
71
-     * After succesful creation of the file, you may choose to return the ETag
72
-     * of the new file here.
73
-     *
74
-     * The returned ETag must be surrounded by double-quotes (The quotes should
75
-     * be part of the actual string).
76
-     *
77
-     * If you cannot accurately determine the ETag, you should not return it.
78
-     * If you don't store the file exactly as-is (you're transforming it
79
-     * somehow) you should also not return an ETag.
80
-     *
81
-     * This means that if a subsequent GET to this new file does not exactly
82
-     * return the same contents of what was submitted here, you are strongly
83
-     * recommended to omit the ETag.
84
-     *
85
-     * @param string $name Name of the file
86
-     * @param resource|string $data Initial payload
87
-     * @return null|string
88
-     */
89
-    public function createFile($name, $data = null) {
90
-
91
-        throw new Exception\Forbidden('Permission denied to create file (filename ' . $name . ')');
92
-
93
-    }
94
-
95
-    /**
96
-     * Creates a new subdirectory
97
-     *
98
-     * @param string $name
99
-     * @throws Exception\Forbidden
100
-     * @return void
101
-     */
102
-    public function createDirectory($name) {
103
-
104
-        throw new Exception\Forbidden('Permission denied to create directory');
105
-
106
-    }
17
+	/**
18
+	 * Returns a child object, by its name.
19
+	 *
20
+	 * This method makes use of the getChildren method to grab all the child
21
+	 * nodes, and compares the name.
22
+	 * Generally its wise to override this, as this can usually be optimized
23
+	 *
24
+	 * This method must throw Sabre\DAV\Exception\NotFound if the node does not
25
+	 * exist.
26
+	 *
27
+	 * @param string $name
28
+	 * @throws Exception\NotFound
29
+	 * @return INode
30
+	 */
31
+	public function getChild($name) {
32
+
33
+		foreach ($this->getChildren() as $child) {
34
+
35
+			if ($child->getName() === $name) return $child;
36
+
37
+		}
38
+		throw new Exception\NotFound('File not found: ' . $name);
39
+
40
+	}
41
+
42
+	/**
43
+	 * Checks is a child-node exists.
44
+	 *
45
+	 * It is generally a good idea to try and override this. Usually it can be optimized.
46
+	 *
47
+	 * @param string $name
48
+	 * @return bool
49
+	 */
50
+	public function childExists($name) {
51
+
52
+		try {
53
+
54
+			$this->getChild($name);
55
+			return true;
56
+
57
+		} catch (Exception\NotFound $e) {
58
+
59
+			return false;
60
+
61
+		}
62
+
63
+	}
64
+
65
+	/**
66
+	 * Creates a new file in the directory
67
+	 *
68
+	 * Data will either be supplied as a stream resource, or in certain cases
69
+	 * as a string. Keep in mind that you may have to support either.
70
+	 *
71
+	 * After succesful creation of the file, you may choose to return the ETag
72
+	 * of the new file here.
73
+	 *
74
+	 * The returned ETag must be surrounded by double-quotes (The quotes should
75
+	 * be part of the actual string).
76
+	 *
77
+	 * If you cannot accurately determine the ETag, you should not return it.
78
+	 * If you don't store the file exactly as-is (you're transforming it
79
+	 * somehow) you should also not return an ETag.
80
+	 *
81
+	 * This means that if a subsequent GET to this new file does not exactly
82
+	 * return the same contents of what was submitted here, you are strongly
83
+	 * recommended to omit the ETag.
84
+	 *
85
+	 * @param string $name Name of the file
86
+	 * @param resource|string $data Initial payload
87
+	 * @return null|string
88
+	 */
89
+	public function createFile($name, $data = null) {
90
+
91
+		throw new Exception\Forbidden('Permission denied to create file (filename ' . $name . ')');
92
+
93
+	}
94
+
95
+	/**
96
+	 * Creates a new subdirectory
97
+	 *
98
+	 * @param string $name
99
+	 * @throws Exception\Forbidden
100
+	 * @return void
101
+	 */
102
+	public function createDirectory($name) {
103
+
104
+		throw new Exception\Forbidden('Permission denied to create directory');
105
+
106
+	}
107 107
 
108 108
 
109 109
 }
Please login to merge, or discard this patch.
libraries/SabreDAV/DAV/TemporaryFileFilterPlugin.php 1 patch
Indentation   +262 added lines, -262 removed lines patch added patch discarded remove patch
@@ -32,266 +32,266 @@
 block discarded – undo
32 32
  */
33 33
 class TemporaryFileFilterPlugin extends ServerPlugin {
34 34
 
35
-    /**
36
-     * This is the list of patterns we intercept.
37
-     * If new patterns are added, they must be valid patterns for preg_match.
38
-     *
39
-     * @var array
40
-     */
41
-    public $temporaryFilePatterns = [
42
-        '/^\._(.*)$/',     // OS/X resource forks
43
-        '/^.DS_Store$/',   // OS/X custom folder settings
44
-        '/^desktop.ini$/', // Windows custom folder settings
45
-        '/^Thumbs.db$/',   // Windows thumbnail cache
46
-        '/^.(.*).swp$/',   // ViM temporary files
47
-        '/^\.dat(.*)$/',   // Smultron seems to create these
48
-        '/^~lock.(.*)#$/', // Windows 7 lockfiles
49
-    ];
50
-
51
-    /**
52
-     * A reference to the main Server class
53
-     *
54
-     * @var Sabre\DAV\Server
55
-     */
56
-    protected $server;
57
-
58
-    /**
59
-     * This is the directory where this plugin
60
-     * will store it's files.
61
-     *
62
-     * @var string
63
-     */
64
-    private $dataDir;
65
-
66
-    /**
67
-     * Creates the plugin.
68
-     *
69
-     * Make sure you specify a directory for your files. If you don't, we
70
-     * will use PHP's directory for session-storage instead, and you might
71
-     * not want that.
72
-     *
73
-     * @param string|null $dataDir
74
-     */
75
-    public function __construct($dataDir = null) {
76
-
77
-        if (!$dataDir) $dataDir = ini_get('session.save_path') . '/sabredav/';
78
-        if (!is_dir($dataDir)) mkdir($dataDir);
79
-        $this->dataDir = $dataDir;
80
-
81
-    }
82
-
83
-    /**
84
-     * Initialize the plugin
85
-     *
86
-     * This is called automatically be the Server class after this plugin is
87
-     * added with Sabre\DAV\Server::addPlugin()
88
-     *
89
-     * @param Server $server
90
-     * @return void
91
-     */
92
-    public function initialize(Server $server) {
93
-
94
-        $this->server = $server;
95
-        $server->on('beforeMethod',    [$this, 'beforeMethod']);
96
-        $server->on('beforeCreateFile', [$this, 'beforeCreateFile']);
97
-
98
-    }
99
-
100
-    /**
101
-     * This method is called before any HTTP method handler
102
-     *
103
-     * This method intercepts any GET, DELETE, PUT and PROPFIND calls to
104
-     * filenames that are known to match the 'temporary file' regex.
105
-     *
106
-     * @param RequestInterface $request
107
-     * @param ResponseInterface $response
108
-     * @return bool
109
-     */
110
-    public function beforeMethod(RequestInterface $request, ResponseInterface $response) {
111
-
112
-        if (!$tempLocation = $this->isTempFile($request->getPath()))
113
-            return;
114
-
115
-        switch ($request->getMethod()) {
116
-            case 'GET' :
117
-                return $this->httpGet($request, $response, $tempLocation);
118
-            case 'PUT' :
119
-                return $this->httpPut($request, $response, $tempLocation);
120
-            case 'PROPFIND' :
121
-                return $this->httpPropfind($request, $response, $tempLocation);
122
-            case 'DELETE' :
123
-                return $this->httpDelete($request, $response, $tempLocation);
124
-        }
125
-        return;
126
-
127
-    }
128
-
129
-    /**
130
-     * This method is invoked if some subsystem creates a new file.
131
-     *
132
-     * This is used to deal with HTTP LOCK requests which create a new
133
-     * file.
134
-     *
135
-     * @param string $uri
136
-     * @param resource $data
137
-     * @param DAV\ICollection $parentNode
138
-     * @param bool $modified Should be set to true, if this event handler
139
-     *                       changed &$data.
140
-     * @return bool
141
-     */
142
-    public function beforeCreateFile($uri, $data, $parent, $modified) {
143
-
144
-        if ($tempPath = $this->isTempFile($uri)) {
145
-
146
-            $hR = $this->server->httpResponse;
147
-            $hR->setHeader('X-Sabre-Temp', 'true');
148
-            file_put_contents($tempPath, $data);
149
-            return false;
150
-        }
151
-        return;
152
-
153
-    }
154
-
155
-    /**
156
-     * This method will check if the url matches the temporary file pattern
157
-     * if it does, it will return an path based on $this->dataDir for the
158
-     * temporary file storage.
159
-     *
160
-     * @param string $path
161
-     * @return bool|string
162
-     */
163
-    protected function isTempFile($path) {
164
-
165
-        // We're only interested in the basename.
166
-        list(, $tempPath) = URLUtil::splitPath($path);
167
-
168
-        foreach ($this->temporaryFilePatterns as $tempFile) {
169
-
170
-            if (preg_match($tempFile, $tempPath)) {
171
-                return $this->getDataDir() . '/sabredav_' . md5($path) . '.tempfile';
172
-            }
173
-
174
-        }
175
-
176
-        return false;
177
-
178
-    }
179
-
180
-
181
-    /**
182
-     * This method handles the GET method for temporary files.
183
-     * If the file doesn't exist, it will return false which will kick in
184
-     * the regular system for the GET method.
185
-     *
186
-     * @param RequestInterface $request
187
-     * @param ResponseInterface $hR
188
-     * @param string $tempLocation
189
-     * @return bool
190
-     */
191
-    public function httpGet(RequestInterface $request, ResponseInterface $hR, $tempLocation) {
192
-
193
-        if (!file_exists($tempLocation)) return;
194
-
195
-        $hR->setHeader('Content-Type', 'application/octet-stream');
196
-        $hR->setHeader('Content-Length', filesize($tempLocation));
197
-        $hR->setHeader('X-Sabre-Temp', 'true');
198
-        $hR->setStatus(200);
199
-        $hR->setBody(fopen($tempLocation, 'r'));
200
-        return false;
201
-
202
-    }
203
-
204
-    /**
205
-     * This method handles the PUT method.
206
-     *
207
-     * @param RequestInterface $request
208
-     * @param ResponseInterface $hR
209
-     * @param string $tempLocation
210
-     * @return bool
211
-     */
212
-    public function httpPut(RequestInterface $request, ResponseInterface $hR, $tempLocation) {
213
-
214
-        $hR->setHeader('X-Sabre-Temp', 'true');
215
-
216
-        $newFile = !file_exists($tempLocation);
217
-
218
-        if (!$newFile && ($this->server->httpRequest->getHeader('If-None-Match'))) {
219
-             throw new Exception\PreconditionFailed('The resource already exists, and an If-None-Match header was supplied');
220
-        }
221
-
222
-        file_put_contents($tempLocation, $this->server->httpRequest->getBody());
223
-        $hR->setStatus($newFile ? 201 : 200);
224
-        return false;
225
-
226
-    }
227
-
228
-    /**
229
-     * This method handles the DELETE method.
230
-     *
231
-     * If the file didn't exist, it will return false, which will make the
232
-     * standard HTTP DELETE handler kick in.
233
-     *
234
-     * @param RequestInterface $request
235
-     * @param ResponseInterface $hR
236
-     * @param string $tempLocation
237
-     * @return bool
238
-     */
239
-    public function httpDelete(RequestInterface $request, ResponseInterface $hR, $tempLocation) {
240
-
241
-        if (!file_exists($tempLocation)) return;
242
-
243
-        unlink($tempLocation);
244
-        $hR->setHeader('X-Sabre-Temp', 'true');
245
-        $hR->setStatus(204);
246
-        return false;
247
-
248
-    }
249
-
250
-    /**
251
-     * This method handles the PROPFIND method.
252
-     *
253
-     * It's a very lazy method, it won't bother checking the request body
254
-     * for which properties were requested, and just sends back a default
255
-     * set of properties.
256
-     *
257
-     * @param RequestInterface $request
258
-     * @param ResponseInterface $hR
259
-     * @param string $tempLocation
260
-     * @return bool
261
-     */
262
-    public function httpPropfind(RequestInterface $request, ResponseInterface $hR, $tempLocation) {
263
-
264
-        if (!file_exists($tempLocation)) return;
265
-
266
-        $hR->setHeader('X-Sabre-Temp', 'true');
267
-        $hR->setStatus(207);
268
-        $hR->setHeader('Content-Type', 'application/xml; charset=utf-8');
269
-
270
-        $properties = [
271
-            'href' => $request->getPath(),
272
-            200    => [
273
-                '{DAV:}getlastmodified'                 => new Xml\Property\GetLastModified(filemtime($tempLocation)),
274
-                '{DAV:}getcontentlength'                => filesize($tempLocation),
275
-                '{DAV:}resourcetype'                    => new Xml\Property\ResourceType(null),
276
-                '{' . Server::NS_SABREDAV . '}tempFile' => true,
277
-
278
-            ],
279
-        ];
280
-
281
-        $data = $this->server->generateMultiStatus([$properties]);
282
-        $hR->setBody($data);
283
-        return false;
284
-
285
-    }
286
-
287
-
288
-    /**
289
-     * This method returns the directory where the temporary files should be stored.
290
-     *
291
-     * @return string
292
-     */
293
-    protected function getDataDir()
294
-    {
295
-        return $this->dataDir;
296
-    }
35
+	/**
36
+	 * This is the list of patterns we intercept.
37
+	 * If new patterns are added, they must be valid patterns for preg_match.
38
+	 *
39
+	 * @var array
40
+	 */
41
+	public $temporaryFilePatterns = [
42
+		'/^\._(.*)$/',     // OS/X resource forks
43
+		'/^.DS_Store$/',   // OS/X custom folder settings
44
+		'/^desktop.ini$/', // Windows custom folder settings
45
+		'/^Thumbs.db$/',   // Windows thumbnail cache
46
+		'/^.(.*).swp$/',   // ViM temporary files
47
+		'/^\.dat(.*)$/',   // Smultron seems to create these
48
+		'/^~lock.(.*)#$/', // Windows 7 lockfiles
49
+	];
50
+
51
+	/**
52
+	 * A reference to the main Server class
53
+	 *
54
+	 * @var Sabre\DAV\Server
55
+	 */
56
+	protected $server;
57
+
58
+	/**
59
+	 * This is the directory where this plugin
60
+	 * will store it's files.
61
+	 *
62
+	 * @var string
63
+	 */
64
+	private $dataDir;
65
+
66
+	/**
67
+	 * Creates the plugin.
68
+	 *
69
+	 * Make sure you specify a directory for your files. If you don't, we
70
+	 * will use PHP's directory for session-storage instead, and you might
71
+	 * not want that.
72
+	 *
73
+	 * @param string|null $dataDir
74
+	 */
75
+	public function __construct($dataDir = null) {
76
+
77
+		if (!$dataDir) $dataDir = ini_get('session.save_path') . '/sabredav/';
78
+		if (!is_dir($dataDir)) mkdir($dataDir);
79
+		$this->dataDir = $dataDir;
80
+
81
+	}
82
+
83
+	/**
84
+	 * Initialize the plugin
85
+	 *
86
+	 * This is called automatically be the Server class after this plugin is
87
+	 * added with Sabre\DAV\Server::addPlugin()
88
+	 *
89
+	 * @param Server $server
90
+	 * @return void
91
+	 */
92
+	public function initialize(Server $server) {
93
+
94
+		$this->server = $server;
95
+		$server->on('beforeMethod',    [$this, 'beforeMethod']);
96
+		$server->on('beforeCreateFile', [$this, 'beforeCreateFile']);
97
+
98
+	}
99
+
100
+	/**
101
+	 * This method is called before any HTTP method handler
102
+	 *
103
+	 * This method intercepts any GET, DELETE, PUT and PROPFIND calls to
104
+	 * filenames that are known to match the 'temporary file' regex.
105
+	 *
106
+	 * @param RequestInterface $request
107
+	 * @param ResponseInterface $response
108
+	 * @return bool
109
+	 */
110
+	public function beforeMethod(RequestInterface $request, ResponseInterface $response) {
111
+
112
+		if (!$tempLocation = $this->isTempFile($request->getPath()))
113
+			return;
114
+
115
+		switch ($request->getMethod()) {
116
+			case 'GET' :
117
+				return $this->httpGet($request, $response, $tempLocation);
118
+			case 'PUT' :
119
+				return $this->httpPut($request, $response, $tempLocation);
120
+			case 'PROPFIND' :
121
+				return $this->httpPropfind($request, $response, $tempLocation);
122
+			case 'DELETE' :
123
+				return $this->httpDelete($request, $response, $tempLocation);
124
+		}
125
+		return;
126
+
127
+	}
128
+
129
+	/**
130
+	 * This method is invoked if some subsystem creates a new file.
131
+	 *
132
+	 * This is used to deal with HTTP LOCK requests which create a new
133
+	 * file.
134
+	 *
135
+	 * @param string $uri
136
+	 * @param resource $data
137
+	 * @param DAV\ICollection $parentNode
138
+	 * @param bool $modified Should be set to true, if this event handler
139
+	 *                       changed &$data.
140
+	 * @return bool
141
+	 */
142
+	public function beforeCreateFile($uri, $data, $parent, $modified) {
143
+
144
+		if ($tempPath = $this->isTempFile($uri)) {
145
+
146
+			$hR = $this->server->httpResponse;
147
+			$hR->setHeader('X-Sabre-Temp', 'true');
148
+			file_put_contents($tempPath, $data);
149
+			return false;
150
+		}
151
+		return;
152
+
153
+	}
154
+
155
+	/**
156
+	 * This method will check if the url matches the temporary file pattern
157
+	 * if it does, it will return an path based on $this->dataDir for the
158
+	 * temporary file storage.
159
+	 *
160
+	 * @param string $path
161
+	 * @return bool|string
162
+	 */
163
+	protected function isTempFile($path) {
164
+
165
+		// We're only interested in the basename.
166
+		list(, $tempPath) = URLUtil::splitPath($path);
167
+
168
+		foreach ($this->temporaryFilePatterns as $tempFile) {
169
+
170
+			if (preg_match($tempFile, $tempPath)) {
171
+				return $this->getDataDir() . '/sabredav_' . md5($path) . '.tempfile';
172
+			}
173
+
174
+		}
175
+
176
+		return false;
177
+
178
+	}
179
+
180
+
181
+	/**
182
+	 * This method handles the GET method for temporary files.
183
+	 * If the file doesn't exist, it will return false which will kick in
184
+	 * the regular system for the GET method.
185
+	 *
186
+	 * @param RequestInterface $request
187
+	 * @param ResponseInterface $hR
188
+	 * @param string $tempLocation
189
+	 * @return bool
190
+	 */
191
+	public function httpGet(RequestInterface $request, ResponseInterface $hR, $tempLocation) {
192
+
193
+		if (!file_exists($tempLocation)) return;
194
+
195
+		$hR->setHeader('Content-Type', 'application/octet-stream');
196
+		$hR->setHeader('Content-Length', filesize($tempLocation));
197
+		$hR->setHeader('X-Sabre-Temp', 'true');
198
+		$hR->setStatus(200);
199
+		$hR->setBody(fopen($tempLocation, 'r'));
200
+		return false;
201
+
202
+	}
203
+
204
+	/**
205
+	 * This method handles the PUT method.
206
+	 *
207
+	 * @param RequestInterface $request
208
+	 * @param ResponseInterface $hR
209
+	 * @param string $tempLocation
210
+	 * @return bool
211
+	 */
212
+	public function httpPut(RequestInterface $request, ResponseInterface $hR, $tempLocation) {
213
+
214
+		$hR->setHeader('X-Sabre-Temp', 'true');
215
+
216
+		$newFile = !file_exists($tempLocation);
217
+
218
+		if (!$newFile && ($this->server->httpRequest->getHeader('If-None-Match'))) {
219
+			 throw new Exception\PreconditionFailed('The resource already exists, and an If-None-Match header was supplied');
220
+		}
221
+
222
+		file_put_contents($tempLocation, $this->server->httpRequest->getBody());
223
+		$hR->setStatus($newFile ? 201 : 200);
224
+		return false;
225
+
226
+	}
227
+
228
+	/**
229
+	 * This method handles the DELETE method.
230
+	 *
231
+	 * If the file didn't exist, it will return false, which will make the
232
+	 * standard HTTP DELETE handler kick in.
233
+	 *
234
+	 * @param RequestInterface $request
235
+	 * @param ResponseInterface $hR
236
+	 * @param string $tempLocation
237
+	 * @return bool
238
+	 */
239
+	public function httpDelete(RequestInterface $request, ResponseInterface $hR, $tempLocation) {
240
+
241
+		if (!file_exists($tempLocation)) return;
242
+
243
+		unlink($tempLocation);
244
+		$hR->setHeader('X-Sabre-Temp', 'true');
245
+		$hR->setStatus(204);
246
+		return false;
247
+
248
+	}
249
+
250
+	/**
251
+	 * This method handles the PROPFIND method.
252
+	 *
253
+	 * It's a very lazy method, it won't bother checking the request body
254
+	 * for which properties were requested, and just sends back a default
255
+	 * set of properties.
256
+	 *
257
+	 * @param RequestInterface $request
258
+	 * @param ResponseInterface $hR
259
+	 * @param string $tempLocation
260
+	 * @return bool
261
+	 */
262
+	public function httpPropfind(RequestInterface $request, ResponseInterface $hR, $tempLocation) {
263
+
264
+		if (!file_exists($tempLocation)) return;
265
+
266
+		$hR->setHeader('X-Sabre-Temp', 'true');
267
+		$hR->setStatus(207);
268
+		$hR->setHeader('Content-Type', 'application/xml; charset=utf-8');
269
+
270
+		$properties = [
271
+			'href' => $request->getPath(),
272
+			200    => [
273
+				'{DAV:}getlastmodified'                 => new Xml\Property\GetLastModified(filemtime($tempLocation)),
274
+				'{DAV:}getcontentlength'                => filesize($tempLocation),
275
+				'{DAV:}resourcetype'                    => new Xml\Property\ResourceType(null),
276
+				'{' . Server::NS_SABREDAV . '}tempFile' => true,
277
+
278
+			],
279
+		];
280
+
281
+		$data = $this->server->generateMultiStatus([$properties]);
282
+		$hR->setBody($data);
283
+		return false;
284
+
285
+	}
286
+
287
+
288
+	/**
289
+	 * This method returns the directory where the temporary files should be stored.
290
+	 *
291
+	 * @return string
292
+	 */
293
+	protected function getDataDir()
294
+	{
295
+		return $this->dataDir;
296
+	}
297 297
 }
Please login to merge, or discard this patch.
libraries/SabreDAV/DAV/IQuota.php 1 patch
Indentation   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -15,12 +15,12 @@
 block discarded – undo
15 15
  */
16 16
 interface IQuota extends ICollection {
17 17
 
18
-    /**
19
-     * Returns the quota information
20
-     *
21
-     * This method MUST return an array with 2 values, the first being the total used space,
22
-     * the second the available space (in bytes)
23
-     */
24
-    public function getQuotaInfo();
18
+	/**
19
+	 * Returns the quota information
20
+	 *
21
+	 * This method MUST return an array with 2 values, the first being the total used space,
22
+	 * the second the available space (in bytes)
23
+	 */
24
+	public function getQuotaInfo();
25 25
 
26 26
 }
Please login to merge, or discard this patch.
libraries/SabreDAV/DAV/IFile.php 1 patch
Indentation   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -15,67 +15,67 @@
 block discarded – undo
15 15
  */
16 16
 interface IFile extends INode {
17 17
 
18
-    /**
19
-     * Replaces the contents of the file.
20
-     *
21
-     * The data argument is a readable stream resource.
22
-     *
23
-     * After a succesful put operation, you may choose to return an ETag. The
24
-     * etag must always be surrounded by double-quotes. These quotes must
25
-     * appear in the actual string you're returning.
26
-     *
27
-     * Clients may use the ETag from a PUT request to later on make sure that
28
-     * when they update the file, the contents haven't changed in the mean
29
-     * time.
30
-     *
31
-     * If you don't plan to store the file byte-by-byte, and you return a
32
-     * different object on a subsequent GET you are strongly recommended to not
33
-     * return an ETag, and just return null.
34
-     *
35
-     * @param resource $data
36
-     * @return string|null
37
-     */
38
-    public function put($data);
18
+	/**
19
+	 * Replaces the contents of the file.
20
+	 *
21
+	 * The data argument is a readable stream resource.
22
+	 *
23
+	 * After a succesful put operation, you may choose to return an ETag. The
24
+	 * etag must always be surrounded by double-quotes. These quotes must
25
+	 * appear in the actual string you're returning.
26
+	 *
27
+	 * Clients may use the ETag from a PUT request to later on make sure that
28
+	 * when they update the file, the contents haven't changed in the mean
29
+	 * time.
30
+	 *
31
+	 * If you don't plan to store the file byte-by-byte, and you return a
32
+	 * different object on a subsequent GET you are strongly recommended to not
33
+	 * return an ETag, and just return null.
34
+	 *
35
+	 * @param resource $data
36
+	 * @return string|null
37
+	 */
38
+	public function put($data);
39 39
 
40
-    /**
41
-     * Returns the data
42
-     *
43
-     * This method may either return a string or a readable stream resource
44
-     *
45
-     * @return mixed
46
-     */
47
-    public function get();
40
+	/**
41
+	 * Returns the data
42
+	 *
43
+	 * This method may either return a string or a readable stream resource
44
+	 *
45
+	 * @return mixed
46
+	 */
47
+	public function get();
48 48
 
49
-    /**
50
-     * Returns the mime-type for a file
51
-     *
52
-     * If null is returned, we'll assume application/octet-stream
53
-     *
54
-     * @return string|null
55
-     */
56
-    public function getContentType();
49
+	/**
50
+	 * Returns the mime-type for a file
51
+	 *
52
+	 * If null is returned, we'll assume application/octet-stream
53
+	 *
54
+	 * @return string|null
55
+	 */
56
+	public function getContentType();
57 57
 
58
-    /**
59
-     * Returns the ETag for a file
60
-     *
61
-     * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change.
62
-     *
63
-     * Return null if the ETag can not effectively be determined.
64
-     *
65
-     * The ETag must be surrounded by double-quotes, so something like this
66
-     * would make a valid ETag:
67
-     *
68
-     *   return '"someetag"';
69
-     *
70
-     * @return string|null
71
-     */
72
-    public function getETag();
58
+	/**
59
+	 * Returns the ETag for a file
60
+	 *
61
+	 * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change.
62
+	 *
63
+	 * Return null if the ETag can not effectively be determined.
64
+	 *
65
+	 * The ETag must be surrounded by double-quotes, so something like this
66
+	 * would make a valid ETag:
67
+	 *
68
+	 *   return '"someetag"';
69
+	 *
70
+	 * @return string|null
71
+	 */
72
+	public function getETag();
73 73
 
74
-    /**
75
-     * Returns the size of the node, in bytes
76
-     *
77
-     * @return int
78
-     */
79
-    public function getSize();
74
+	/**
75
+	 * Returns the size of the node, in bytes
76
+	 *
77
+	 * @return int
78
+	 */
79
+	public function getSize();
80 80
 
81 81
 }
Please login to merge, or discard this patch.