r37162 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r37161‎ | r37162 | r37163 >
Date:12:06, 6 July 2008
Author:shinjiman
Status:old
Tags:
Comment:
some leftout on the previous commit r37161
Modified paths:
  • /trunk/extensions/WebDAV/WebDav.php (deleted) (history)

Diff [purge]

Index: trunk/extensions/WebDAV/WebDav.php
@@ -1,779 +0,0 @@
2 -<?php
3 -
4 -define( 'MW_SEARCH_LIMIT', 50 );
5 -
6 -require_once( './lib/HTTP/WebDAV/Server.php' );
7 -
8 -class WebDavServer extends HTTP_WebDAV_Server {
9 -
10 - function init() {
11 - parent::init();
12 -
13 - # Prepend script path component to path components
14 - array_unshift( $this->pathComponents, array_pop( $this->baseUrlComponents['pathComponents'] ) );
15 - }
16 -
17 - function getAllowedMethods() {
18 - return array( 'OPTIONS', 'PROPFIND', 'GET', 'HEAD', 'DELETE', 'PUT', 'REPORT', 'SEARCH' );
19 - }
20 -
21 - function options( &$serverOptions ) {
22 - parent::options( &$serverOptions );
23 -
24 - if ( $serverOptions['xpath']->evaluate( 'boolean(/D:options/D:activity-collection-set)' ) ) {
25 - $this->setResponseHeader( 'Content-Type: text/xml; charset="utf-8"' );
26 -
27 - echo "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
28 - echo "<D:options-response xmlns:D=\"DAV:\">\n";
29 - echo ' <D:activity-collection-set><D:href>' . $this->getUrl( array( 'path' => 'deltav.php/act' ) ) . "</D:href></D:activity-collection-set>\n";
30 - echo "</D:options-response>\n";
31 - }
32 -
33 - return true;
34 - }
35 -
36 - function propfind( &$serverOptions ) {
37 - if ( empty( $this->pathComponents ) ) {
38 - return;
39 - }
40 - $pathComponent = array_shift( $this->pathComponents );
41 - if ( $pathComponent != 'deltav.php' && $pathComponent != 'webdav.php' ) {
42 - return;
43 - }
44 -
45 - if ( $pathComponent == 'deltav.php' ) {
46 - if ( empty( $this->pathComponents ) ) {
47 - return;
48 - }
49 - $pathComponent = array_shift( $this->pathComponents );
50 - if ( $pathComponent != 'bc' && $pathComponent != 'bln' && $pathComponent != 'vcc' && $pathComponent != 'ver' ) {
51 - return;
52 - }
53 -
54 - if ( $pathComponent == 'vcc' ) {
55 - if ( empty( $this->pathComponents ) ) {
56 - return;
57 - }
58 - $pathComponent = array_shift( $this->pathComponents );
59 - if ( $pathComponent != 'default' ) {
60 - return;
61 - }
62 - if ( !empty( $this->pathComponents ) ) {
63 - return;
64 - }
65 -
66 - if ( isset( $serverOptions['label'] ) ) {
67 - return $this->propfindBln( $serverOptions, $serverOptions['label'] );
68 - }
69 -
70 - return $this->propfindVcc( $serverOptions );
71 - }
72 -
73 - if ( empty( $this->pathComponents ) ) {
74 - return;
75 - }
76 - $revisionId = array_shift( $this->pathComponents );
77 -
78 - if ( $pathComponent == 'bc' ) {
79 - return $this->propfindBc( $serverOptions, $revisionId, $this->pathComponents );
80 - }
81 -
82 - if ( !empty( $this->pathComponents ) ) {
83 - return;
84 - }
85 -
86 - if ( $pathComponent == 'bln' ) {
87 - return $this->propfindBln( $serverOptions, $revisionId );
88 - }
89 -
90 - return $this->propfindVer( $serverOptions, $revisionId );
91 - }
92 -
93 - if ( isset( $serverOptions['label'] ) ) {
94 - # TODO: Verify revision belongs to this resource, or should we care?
95 - return $this->propfindVer( $serverOptions, $serverOptions['label'] );
96 - }
97 -
98 - $serverOptions['namespaces']['http://subversion.tigris.org/xmlns/dav/'] = 'V';
99 -
100 - $status = array();
101 -
102 - # Handle root collection
103 - if ( empty( $this->pathComponents ) ) {
104 - global $wgSitename;
105 -
106 - $response = array();
107 - $response['path'] = 'webdav.php/';
108 -
109 - # TODO: Use Main_Page revision?
110 - $response['props'][] = WebDavServer::mkprop( 'checked-in', $this->getUrl( array( 'path' => 'deltav.php/ver' ) ) );
111 -
112 - $response['props'][] = WebDavServer::mkprop( 'displayname', $wgSitename );
113 - $response['props'][] = WebDavServer::mkprop( 'getcontentlength', 0 );
114 - $response['props'][] = WebDavServer::mkprop( 'getcontenttype', 'httpd/unix-directory' );
115 - $response['props'][] = WebDavServer::mkprop( 'resourcetype', 'collection' );
116 - $response['props'][] = WebDavServer::mkprop( 'version-controlled-configuration', $this->getUrl( array( 'path' => 'deltav.php/vcc/default' ) ) );
117 -
118 - $response['props'][] = WebDavServer::mkprop( 'http://subversion.tigris.org/xmlns/dav/', 'baseline-relative-path', null );
119 -
120 - # TODO: Don't hardcode this
121 - $response['props'][] = WebDavServer::mkprop( 'http://subversion.tigris.org/xmlns/dav/', 'repository-uuid', '87a9137c-6795-46f8-83b9-2ee953e66e08' );
122 -
123 - $status[] = $response;
124 -
125 - # Don't descend if depth is zero
126 - if ( empty( $serverOptions['depth'] ) ) {
127 - return $status;
128 - }
129 - }
130 -
131 - # TODO: Use $wgMemc
132 - $dbr =& wfGetDB( DB_SLAVE );
133 -
134 - # TODO: Think harder about pages' hierarchical structure. The trouble is most filesystems don't support directories which themselves have file content, which is a problem for making pages descendents of other pages.
135 - $where = array();
136 - if ( !empty( $this->pathComponents ) ) {
137 - $where[] = 'page_title = ' . $dbr->addQuotes( implode( '/', $this->pathComponents ) );
138 - }
139 -
140 - $whereClause = null;
141 - if ( !empty( $where ) ) {
142 - $whereClause = ' WHERE ' . implode( ' AND ', $where );
143 - }
144 - $results = $dbr->query( '
145 - SELECT page_title, page_latest, page_len, page_touched
146 - FROM page' . $whereClause );
147 -
148 - while ( ( $result = $dbr->fetchRow( $results ) ) !== false ) {
149 - # TODO: Should maybe not be using page_title as URL component, but it's currently what we do elsewhere
150 - $title = Title::newFromUrl( $result[0] );
151 -
152 - $response = array();
153 - $response['path'] = 'webdav.php/' . $result[0];
154 - $response['props'][] = WebDavServer::mkprop( 'checked-in', $this->getUrl( array( 'path' => 'deltav.php/ver/' . $result[1] ) ) );
155 - $response['props'][] = WebDavServer::mkprop( 'displayname', $title->getText() );
156 - $response['props'][] = WebDavServer::mkprop( 'getcontentlength', $result[2] );
157 - $response['props'][] = WebDavServer::mkprop( 'getcontenttype', 'text/x-wiki' );
158 - $response['props'][] = WebDavServer::mkprop( 'getlastmodified', wfTimestamp( TS_UNIX, $result[3] ) );
159 - $response['props'][] = WebDavServer::mkprop( 'resourcetype', null );
160 - $response['props'][] = WebDavServer::mkprop( 'version-controlled-configuration', $this->getUrl( array( 'path' => 'deltav.php/vcc/default' ) ) );
161 -
162 - $response['props'][] = WebDavServer::mkprop( 'http://subversion.tigris.org/xmlns/dav/', 'baseline-relative-path', $result[0] );
163 -
164 - $status[] = $response;
165 - }
166 -
167 - return $status;
168 - }
169 -
170 - function propfindBc( &$serverOptions, $revisionId, $pathComponents ) {
171 - $serverOptions['namespaces']['http://subversion.tigris.org/xmlns/dav/'] = 'V';
172 -
173 - $status = array();
174 -
175 - # TODO: Verify $revisionId is valid
176 - # Handle root collection
177 - if ( empty( $pathComponents ) ) {
178 - global $wgSitename;
179 -
180 - $response = array();
181 - $response['path'] = 'deltav.php/bc/' . $revisionId . '/';
182 - # TODO: Use Main_Page revision?
183 - $response['props'][] = WebDavServer::mkprop( 'checked-in', $this->getUrl( array( 'path' => 'deltav.php/ver' ) ) );
184 -
185 - $response['props'][] = WebDavServer::mkprop( 'displayname', $wgSitename );
186 - $response['props'][] = WebDavServer::mkprop( 'getcontentlength', 0 );
187 - $response['props'][] = WebDavServer::mkprop( 'getcontenttype', 'httpd/unix-directory' );
188 - $response['props'][] = WebDavServer::mkprop( 'resourcetype', 'collection' );
189 - $response['props'][] = WebDavServer::mkprop( 'version-controlled-configuration', $this->getUrl( array( 'path' => 'deltav.php/vcc/default' ) ) );
190 - $response['props'][] = WebDavServer::mkprop( 'version-name', null );
191 -
192 - $response['props'][] = WebDavServer::mkprop( 'http://subversion.tigris.org/xmlns/dav/', 'baseline-relative-path', null );
193 -
194 - # TODO: Don't hardcode this
195 - $response['props'][] = WebDavServer::mkprop( 'http://subversion.tigris.org/xmlns/dav/', 'repository-uuid', '87a9137c-6795-46f8-83b9-2ee953e66e08' );
196 -
197 - $status[] = $response;
198 -
199 - # Don't descend if depth is zero
200 - if ( empty( $serverOptions['depth'] ) ) {
201 - return $status;
202 - }
203 - }
204 -
205 - # TODO: Use $wgMemc
206 - $dbr =& wfGetDB( DB_SLAVE );
207 -
208 - # TODO: Think harder about pages' hierarchical structure. The trouble is most filesystems don't support directories which themselves have file content, which is a problem for making pages descendents of other pages.
209 - $where = array();
210 - $where[] = 'rev_page = page_id';
211 - $where[] = 'rev_id <= ' . $dbr->addQuotes( $revisionId );
212 - if ( !empty( $pathComponents ) ) {
213 - $where[] = 'page_title = ' . $dbr->addQuotes( implode( '/', $pathComponents ) );
214 - }
215 -
216 - $whereClause = null;
217 - if ( !empty( $where ) ) {
218 - $whereClause = ' WHERE ' . implode( ' AND ', $where );
219 - }
220 - $results = $dbr->query( '
221 - SELECT page_title, MAX(rev_id), page_len, page_touched
222 - FROM page, revision' . $whereClause . '
223 - GROUP BY page_id' );
224 -
225 - while ( ( $result = $dbr->fetchRow( $results ) ) !== false ) {
226 - # TODO: Should maybe not be using page_title as URL component, but it's currently what we do elsewhere
227 - $title = Title::newFromUrl( $result[0] );
228 -
229 - $response = array();
230 - $response['path'] = 'deltav.php/bc/' . $revisionId . '/' . $result[0];
231 - $response['props'][] = WebDavServer::mkprop( 'checked-in', $this->getUrl( array( 'path' => 'deltav.php/ver/' . $result[1] ) ) );
232 - $response['props'][] = WebDavServer::mkprop( 'displayname', $title->getText() );
233 - $response['props'][] = WebDavServer::mkprop( 'getcontentlength', $result[2] );
234 - $response['props'][] = WebDavServer::mkprop( 'getcontenttype', 'text/x-wiki' );
235 - $response['props'][] = WebDavServer::mkprop( 'getlastmodified', wfTimestamp( TS_UNIX, $result[3] ) );
236 - $response['props'][] = WebDavServer::mkprop( 'resourcetype', null );
237 - $response['props'][] = WebDavServer::mkprop( 'version-controlled-configuration', $this->getUrl( array( 'path' => 'deltav.php/vcc/default' ) ) );
238 - $response['props'][] = WebDavServer::mkprop( 'version-name', $result[1] );
239 -
240 - $response['props'][] = WebDavServer::mkprop( 'http://subversion.tigris.org/xmlns/dav/', 'baseline-relative-path', $result[0] );
241 -
242 - # TODO: Don't hardcode this
243 - $response['props'][] = WebDavServer::mkprop( 'http://subversion.tigris.org/xmlns/dav/', 'repository-uuid', '87a9137c-6795-46f8-83b9-2ee953e66e08' );
244 -
245 - $status[] = $response;
246 - }
247 -
248 - return $status;
249 - }
250 -
251 - function propfindBln( &$serverOptions, $revisionId ) {
252 - $response = array();
253 - $response['path'] = 'bln/' . $revisionId;
254 - $response['props'][] = WebDavServer::mkprop( 'baseline-collection', $this->getUrl( array( 'path' => 'deltav.php/bc/' . $revisionId . '/' ) ) );
255 - $response['props'][] = WebDavServer::mkprop( 'version-name', $revisionId );
256 -
257 - return array( $response );
258 - }
259 -
260 - function propfindVcc( &$serverOptions ) {
261 - # TODO: Use $wgMemc
262 - $dbr =& wfGetDB( DB_SLAVE );
263 -
264 - $results = $dbr->query( '
265 - SELECT MAX(rev_id)
266 - FROM revision' );
267 -
268 - if ( ( $result = $dbr->fetchRow( $results ) ) === false ) {
269 - return;
270 - }
271 -
272 - $response = array();
273 - $response['path'] = 'deltav.php/vcc/default';
274 - $response['props'][] = WebDavServer::mkprop( 'checked-in', $this->getUrl( array( 'path' => 'deltav.php/bln/' . $result[0] ) ) );
275 -
276 - return array( $response );
277 - }
278 -
279 - function propfindVer( &$serverOptions, $revisionId ) {
280 - $response = array();
281 - $response['path'] = 'deltav.php/ver/' . $revisionId;
282 - $response['props'][] = WebDavServer::mkprop( 'resourcetype', null );
283 - #$response['props'][] = WebDavServer::mkprop( 'version-controlled-configuration', $this->getUrl( array( 'path' => 'deltav.php/vcc/default' ) ) );
284 -
285 - #$response['props'][] = WebDavServer::mkprop( 'http://subversion.tigris.org/xmlns/dav/', 'baseline-relative-path', null );
286 -
287 - return array( $response );
288 - }
289 -
290 - function getRawPage() {
291 - if ( empty( $this->pathComponents ) ) {
292 - return;
293 - }
294 - $pathComponent = array_shift( $this->pathComponents );
295 - if ( $pathComponent != 'deltav.php' && $pathComponent != 'webdav.php' ) {
296 - return;
297 - }
298 -
299 - if ( $pathComponent == 'deltav.php' ) {
300 - if ( empty( $this->pathComponents ) ) {
301 - return;
302 - }
303 - $pathComponent = array_shift( $this->pathComponents );
304 - if ( $pathComponent != 'bc' && $pathComponent != 'ver' ) {
305 - return;
306 - }
307 -
308 - if ( empty( $this->pathComponents ) ) {
309 - return;
310 - }
311 - $revisionId = array_shift( $this->pathComponents );
312 -
313 - if ( $pathComponent == 'bc' ) {
314 - $title = Title::newFromUrl( implode( '/', $this->pathComponents ) );
315 - if (!isset( $title )) {
316 - $title = Title::newMainPage();
317 - }
318 - } else {
319 - if ( !empty( $this->pathComponents ) ) {
320 - return;
321 - }
322 -
323 - $revision = Revision::newFromId( $revisionId );
324 - $title = $revision->getTitle();
325 - }
326 - } else {
327 - if ( isset( $serverOptions['label'] ) ) {
328 - # TODO: Verify revision belongs to this resource, or should we care?
329 - $revisionId = $serverOptions['label'];
330 - }
331 -
332 - $title = Title::newFromUrl( implode( '/', $this->pathComponents ) );
333 - if (!isset( $title )) {
334 - $title = Title::newMainPage();
335 - }
336 - }
337 -
338 - $mediaWiki = new MediaWiki();
339 - $article = $mediaWiki->articleFromTitle( $title );
340 -
341 - $rawPage = new RawPage( $article );
342 -
343 - if ( isset( $revisionId ) ) {
344 - $rawPage->mOldId = $revisionId;
345 - }
346 -
347 - return $rawPage;
348 - }
349 -
350 - # RawPage::view handles Content-Type, Cache-Control, etc. and we don't want get_response_helper to overwrite, but MediaWiki doesn't let us get response headers. It could work if we kept setResponseHeader updated with headers_list on PHP 5.
351 - function get_wrapper() {
352 - $rawPage = $this->getRawPage();
353 - if ( !isset( $rawPage ) ) {
354 - $this->setResponseStatus( false, false );
355 - return;
356 - }
357 -
358 - $rawPage->view();
359 - }
360 -
361 - function head_wrapper() {
362 - $rawPage = $this->getRawPage();
363 - if ( !isset( $rawPage ) ) {
364 - $this->setResponseStatus( false, false );
365 - return;
366 - }
367 -
368 - # TODO: Does MediaWiki handle HEAD requests specially?
369 - ob_start();
370 - $rawPage->view();
371 - ob_end_clean();
372 - }
373 -
374 - function delete( $serverOptions ) {
375 - global $wgUser;
376 -
377 - if ( !$wgUser->isAllowed( 'delete' ) ) {
378 - $this->setResponseStatus( '401 Unauthorized' );
379 - return;
380 - }
381 -
382 - if ( wfReadOnly() ) {
383 - $this->setResponseStatus( '403 Forbidden' );
384 - return;
385 - }
386 -
387 - if ( empty( $this->pathComponents ) ) {
388 - return;
389 - }
390 - $pathComponent = array_shift( $this->pathComponents );
391 - if ( $pathComponent != 'webdav.php' ) {
392 - return;
393 - }
394 -
395 - $title = Title::newFromUrl( implode( '/', $this->pathComponents ) );
396 - if (!isset( $title )) {
397 - $title = Title::newMainPage();
398 - }
399 -
400 - $mediaWiki = new MediaWiki();
401 - $article = $mediaWiki->articleFromTitle( $title );
402 -
403 - # Must check if article exists to avoid 500 Internal Server Error
404 -
405 - # No way to get reason for deletion. Can't use null: MySQL returned error "<tt>1048: Column 'log_comment' cannot be null (localhost)</tt>".
406 - $article->doDelete( null );
407 - }
408 -
409 - function put( $serverOptions ) {
410 - global $wgUser;
411 -
412 - if ( !$wgUser->isAllowed( 'edit' ) ) {
413 - $this->setResponseStatus( '401 Unauthorized' );
414 - return;
415 - }
416 -
417 - if ( wfReadOnly() ) {
418 - $this->setResponseStatus( '403 Forbidden' );
419 - return;
420 - }
421 -
422 - if ( empty( $this->pathComponents ) ) {
423 - return;
424 - }
425 - $pathComponent = array_shift( $this->pathComponents );
426 - if ( $pathComponent != 'webdav.php' ) {
427 - return;
428 - }
429 -
430 - $title = Title::newFromUrl( implode( '/', $this->pathComponents ) );
431 - if (!isset( $title )) {
432 - $title = Title::newMainPage();
433 - }
434 -
435 - if ( !$title->exists() && !$title->userCan( 'create' ) ) {
436 - $this->setResponseStatus( '401 Unauthorized' );
437 - return;
438 - }
439 -
440 - $mediaWiki = new MediaWiki();
441 - $article = $mediaWiki->articleFromTitle( $title );
442 -
443 - if ( ( $handle = $this->openRequestBody() ) === false ) {
444 - return;
445 - }
446 -
447 - $text = null;
448 - while ( !feof( $handle ) ) {
449 - if ( ( $buffer = fread( $handle, 4096 ) ) === false ) {
450 - return;
451 - }
452 -
453 - $text .= $buffer;
454 - }
455 -
456 - $article->doEdit( $text, null );
457 -
458 - return true;
459 - }
460 -
461 - function versionTreeReport( &$serverOptions ) {
462 - if ( empty( $this->pathComponents ) ) {
463 - return;
464 - }
465 - $pathComponent = array_shift( $this->pathComponents );
466 - if ( $pathComponent != 'deltav.php' && $pathComponent != 'webdav.php' ) {
467 - return;
468 - }
469 -
470 - $serverOptions['props'] = array();
471 - foreach ( $serverOptions['xpath']->query( '/D:version-tree/D:prop/*' ) as $node) {
472 - $serverOptions['props'][] = $this->mkprop( $node->namespaceURI, $node->localName, null );
473 -
474 - # Namespace handling
475 - if ( empty( $node->namespaceURI ) || empty( $node->prefix ) ) {
476 - continue;
477 - }
478 -
479 - # http://bugs.php.net/bug.php?id=42082
480 - #$serverOptions['namespaces'][$node->namespaceURI] = $node->prefix;
481 - }
482 -
483 - if (empty($serverOptions['props'])) {
484 - $serverOptions['props'] = $serverOptions['xpath']->evaluate( 'local-name(/D:version-tree/*)' );
485 - }
486 -
487 - $status = array();
488 -
489 - # Handle root collection
490 - if ( empty( $this->pathComponents ) ) {
491 - $response = array();
492 - $response['props'][] = WebDavServer::mkprop( 'getcontentlength', 0 );
493 - $response['props'][] = WebDavServer::mkprop( 'getcontenttype', 'httpd/unix-directory' );
494 - $response['props'][] = WebDavServer::mkprop( 'resourcetype', 'collection' );
495 -
496 - $status[] = $response;
497 -
498 - # Don't descend if depth is zero
499 - if ( empty( $serverOptions['depth'] ) ) {
500 - return $status;
501 - }
502 - }
503 -
504 - # TODO: Use $wgMemc
505 - $dbr =& wfGetDB( DB_SLAVE );
506 -
507 - # TODO: Think harder about pages' hierarchical structure. The trouble is most filesystems don't support directories which themselves have file content, which is a problem for making pages descendents of other pages.
508 - $where = array();
509 - $where[] = 'rev_page = page_id';
510 - if ( !empty( $this->pathComponents ) ) {
511 - $where[] = 'page_title = ' . $dbr->addQuotes( implode( '/', $this->pathComponents ) );
512 - }
513 -
514 - $whereClause = null;
515 - if ( !empty( $where ) ) {
516 - $whereClause = ' WHERE ' . implode( ' AND ', $where );
517 - }
518 - $results = $dbr->query( '
519 - SELECT page_title, rev_id, rev_comment, rev_user_text, rev_len, rev_timestamp, rev_parent_id
520 - FROM page, revision' . $whereClause );
521 -
522 - $successors = array();
523 - while ( ( $result = $dbr->fetchRow( $results ) ) !== false ) {
524 - $response = array();
525 - $response['path'] = 'deltav.php/ver/' . $result[1];
526 - $response['props'][] = WebDavServer::mkprop( 'comment', $result[2] );
527 - $response['props'][] = WebDavServer::mkprop( 'creator-displayname', $result[3] );
528 - $response['props'][] = WebDavServer::mkprop( 'getcontentlength', $result[4] );
529 - $response['props'][] = WebDavServer::mkprop( 'getcontenttype', 'text/x-wiki' );
530 - $response['props'][] = WebDavServer::mkprop( 'getlastmodified', wfTimestamp( TS_UNIX, $result[5] ) );
531 - $response['props'][] = WebDavServer::mkprop( 'predecessor-set', array( $result[6] ) );
532 - $response['props'][] = WebDavServer::mkprop( 'resourcetype', null );
533 - $response['props'][] = WebDavServer::mkprop( 'successor-set', array() );
534 - $response['props'][] = WebDavServer::mkprop( 'version-name', $result[1] );
535 -
536 - $status[$result[1]] = $response;
537 -
538 - # Build successor-set
539 - $successors[$result[6]][] = $result[1];
540 - }
541 -
542 - return $status;
543 - }
544 -
545 - function updateReport( &$serverOptions ) {
546 - if ( empty( $this->pathComponents ) ) {
547 - return;
548 - }
549 - $pathComponent = array_shift( $this->pathComponents );
550 - if ( $pathComponent != 'deltav.php' ) {
551 - return;
552 - }
553 -
554 - if ( empty( $this->pathComponents ) ) {
555 - return;
556 - }
557 - $pathComponent = array_shift( $this->pathComponents );
558 - if ( $pathComponent != 'vcc' ) {
559 - return;
560 - }
561 -
562 - if ( empty( $this->pathComponents ) ) {
563 - return;
564 - }
565 - $pathComponent = array_shift( $this->pathComponents );
566 - if ( $pathComponent != 'default' ) {
567 - return;
568 - }
569 - if ( !empty( $this->pathComponents ) ) {
570 - return;
571 - }
572 -
573 - # TODO: Can we ignore this?
574 - if ( isset( $serverOptions['label'] ) ) {
575 - return;
576 - }
577 -
578 - $serverOptions['xpath']->registerNamespace( 'S', 'svn:' );
579 -
580 - # TODO: Error checking?
581 - $targetRevision = $serverOptions['xpath']->evaluate( 'string(/S:update-report/S:target-revision)' );
582 -
583 - # src-path is a misnomer, it's a URL
584 - $srcPath = $serverOptions['xpath']->evaluate( 'string(/S:update-report/S:src-path)' );
585 - $srcComponents = $this->parseUrl( $srcPath );
586 - $srcComponents['pathComponents'] = array_slice( $srcComponents['pathComponents'], count( $this->baseUrlComponents['pathComponents'] ) + 1 );
587 -
588 - # TODO: Use $wgMemc
589 - $dbr =& wfGetDB( DB_SLAVE );
590 -
591 - $entryConditions = array();
592 - foreach ( $serverOptions['xpath']->query( '/S:update-report/S:entry' ) as $node ) {
593 - $entryConditions[$node->textContent] = null;
594 - if ( !$node->hasAttribute( 'start-empty' ) ) {
595 -
596 - # TODO: Error checking?
597 - $entryConditions[$node->textContent] = 'new.rev_id > ' . $dbr->addQuotes( $node->getAttribute( 'rev' ) );
598 - }
599 - }
600 -
601 - function cmp( $a, $b ) {
602 - return strlen( $a ) - strlen( $b );
603 - }
604 - uksort( $entryConditions, 'cmp' );
605 -
606 - $entryCondition = null;
607 - foreach ( $entryConditions as $path => $revisionCondition ) {
608 - if ( !empty( $path ) ) {
609 - $pathCondition = '(page_title = ' . $dbr->addQuotes( $path ) . ' OR page_title LIKE \'' . $dbr->escapeLike( $path ) . '/%\')';
610 -
611 - if ( !empty( $revisionCondition ) ) {
612 - $revisionCondition = ' AND ' . $revisionCondition;
613 - }
614 - $revisionCondition = $pathCondition . $revisionCondition;
615 -
616 - if ( !empty( $entryCondition ) ) {
617 - $entryCondition = ' AND ' . $entryCondition;
618 - }
619 - $entryCondition = 'NOT ' . $pathCondition . $entryCondition;
620 - }
621 -
622 - if ( !empty( $revisionCondition ) ) {
623 - if ( !empty( $entryCondition ) ) {
624 - $revisionCondition = '(' . $revisionCondition;
625 - $entryCondition = ' OR ' . $entryCondition . ')';
626 - }
627 - $entryCondition = $revisionCondition . $entryCondition;
628 - }
629 - }
630 - if ( !empty( $entryCondition ) ) {
631 - $entryCondition = ' AND ' . $entryCondition;
632 - }
633 -
634 - $where = array();
635 - if ( !empty( $targetRevision ) ) {
636 - $where[] = 'old.rev_id <= ' . $dbr->addQuotes( $targetRevision );
637 - }
638 - if ( !empty( $srcComponents['pathComponents'] ) ) {
639 - $where[] = 'page_title = ' . $dbr->addQuotes( implode( '/', $srcComponents['pathComponents'] ) );
640 - }
641 -
642 - if ( empty( $targetRevision ) ) {
643 - $results = $dbr->query( '
644 - SELECT MAX(rev_id)
645 - FROM revision' );
646 -
647 - if ( ( $result = $dbr->fetchRow( $results ) ) === false ) {
648 - return;
649 - }
650 -
651 - $targetRevision = $result[0];
652 - }
653 -
654 - $this->setResponseHeader( 'Content-Type: text/xml; charset="utf-8"', false );
655 -
656 - echo "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
657 - echo "<S:update-report xmlns:D=\"DAV:\" xmlns:S=\"svn:\" xmlns:V=\"http://subversion.tigris.org/xmlns/dav\" send-all=\"true\">\n";
658 -
659 - # TODO: Get the revision from the report request
660 - echo " <S:target-revision rev=\"$targetRevision\"/>\n";
661 -
662 - # TODO: Use Main_Page revision?
663 - echo " <S:open-directory rev=\"$targetRevision\">\n";
664 - echo ' <D:checked-in><D:href>' . $this->getUrl( array( 'path' => 'deltav.php/ver' ) ) . "</D:href></D:checked-in>\n";
665 -
666 - $whereClause = null;
667 - if ( !empty( $where ) ) {
668 - $whereClause = ' WHERE ' . implode( ' AND ', $where );
669 - }
670 -
671 - # SUM(new.rev_id IS NULL) is the number of revisions which didn't match the entry condition
672 - # TODO: Invert entry condition to make getting the base revision cleaner
673 - $results = $dbr->query( '
674 - SELECT page_title, SUM(new.rev_id IS NULL), MAX(CASE WHEN new.rev_id IS NULL THEN old.rev_id ELSE NULL END), MAX(new.rev_id)
675 - FROM page
676 - JOIN revision AS old
677 - ON page_id = old.rev_page
678 - LEFT JOIN revision AS new
679 - ON old.rev_id = new.rev_id' . $entryCondition . $whereClause . '
680 - GROUP BY page_id
681 - HAVING COUNT(new.rev_id)' );
682 -
683 - while ( ( $result = $dbr->fetchRow( $results ) ) !== false ) {
684 - $addOrOpen = 'add';
685 - $baseRev = null;
686 -
687 - $newText = Revision::newFromId( $result[3] )->revText();
688 - $oldText = null;
689 -
690 - if ( $result[1] > 0 ) {
691 - $addOrOpen = 'open';
692 - $baseRev = ' rev="' . $result[2] . '"';
693 -
694 - $oldText = Revision::newFromId( $result[2] )->revText();
695 - }
696 -
697 - # TODO: Use only last path component
698 - echo " <S:$addOrOpen-file name=\"$result[0]\"$baseRev>\n";
699 -
700 - echo ' <D:checked-in><D:href>' . $this->getUrl( array( 'path' => 'deltav.php/ver/' . $result[3] ) ) . "</D:href></D:checked-in>\n";
701 - echo ' <S:txdelta>' . base64_encode( $this->getSvnDiff( $oldText, $newText ) ) . "\n</S:txdelta>\n";
702 - echo ' <S:prop><V:md5-checksum>' . md5( $newText ) . "</V:md5-checksum></S:prop>\n";
703 - echo " </S:$addOrOpen-file>\n";
704 - }
705 -
706 - echo " </S:open-directory>\n";
707 - echo "</S:update-report>\n";
708 -
709 - return true;
710 - }
711 -
712 - function getSvnDiff( $oldText, $newText ) {
713 - $instructions = chr( 0x80 | strlen( $newText ) );
714 - if ( strlen( $newText ) > 0x37 ) {
715 - $instructions = "\x80" . $this->encodeInt( strlen( $newText ) );
716 - }
717 -
718 - return "SVN\x00\x00"
719 - . $this->encodeInt( strlen( $oldText ) )
720 - . $this->encodeInt( strlen( $newText ) )
721 - . $this->encodeInt( strlen( $instructions ) )
722 - . $this->encodeInt( strlen( $newText ) )
723 - . $instructions
724 - . $newText;
725 - }
726 -
727 - function encodeInt( $int ) {
728 - # Least seven bits
729 - $bytes = chr( $int & 0x7f );
730 -
731 - # Shift by seven bits until nothing remains
732 - while ( 0 < $int >>= 7 ) {
733 - # Prepend seven bits with the eighth bit, the continuation bit, set, to the string of bytes
734 - $bytes = chr( $int & 0x7f | 0x80 ) . $bytes;
735 - }
736 -
737 - return $bytes;
738 - }
739 -
740 - function search( &$serverOptions ) {
741 - $serverOptions['namespaces']['http://subversion.tigris.org/xmlns/dav/'] = 'V';
742 -
743 - $status = array();
744 -
745 - $search = SearchEngine::create();
746 -
747 - # TODO: Use (int)$wgUser->getOption( 'searchlimit' );
748 - $search->setLimitOffset( MW_SEARCH_LIMIT );
749 -
750 - $results = $search->searchText( $serverOptions['xpath']->evaluate( 'string(/D:searchrequest/D:basicsearch/D:where/D:contains)' ) );
751 -
752 - while ( ( $result = $results->next() ) !== false ) {
753 - $title = $result->getTitle();
754 - $revision = Revision::newFromTitle( $title );
755 -
756 - $response = array();
757 - $response['path'] = 'webdav.php/' . $title->getPrefixedUrl();
758 - $response['props'][] = WebDavServer::mkprop( 'checked-in', $this->getUrl( array( 'path' => 'deltav.php/ver/' . $revision->getId() ) ) );
759 - $response['props'][] = WebDavServer::mkprop( 'displayname', $title->getText() );
760 - $response['props'][] = WebDavServer::mkprop( 'getcontentlength', $revision->getSize() );
761 - $response['props'][] = WebDavServer::mkprop( 'getcontenttype', 'text/x-wiki' );
762 - $response['props'][] = WebDavServer::mkprop( 'getlastmodified', wfTimestamp( TS_UNIX, $revision->mTimestamp ) );
763 - $response['props'][] = WebDavServer::mkprop( 'resourcetype', null );
764 - $response['props'][] = WebDavServer::mkprop( 'version-controlled-configuration', $this->getUrl( array( 'path' => 'deltav.php/vcc/default' ) ) );
765 -
766 - $response['props'][] = WebDavServer::mkprop( 'http://subversion.tigris.org/xmlns/dav/', 'baseline-relative-path', $title->getFullUrl() );
767 - $response['score'] = $result->getScore();
768 -
769 - $status[] = $response;
770 - }
771 -
772 - # TODO: Check if we exceed our limit
773 - #$response = array();
774 - #$response['status'] = '507 Insufficient Storage';
775 -
776 - #$status[] = $response;
777 -
778 - return $status;
779 - }
780 -}

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r37161Renaming WebDav.php to WebDavServer.php....shinjiman12:04, 6 July 2008

Status & tagging log