ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.ilDAVLocks.php
Go to the documentation of this file.
1<?php
2// BEGIN WebDAV
3/*
4 +-----------------------------------------------------------------------------+
5 | ILIAS open source |
6 +-----------------------------------------------------------------------------+
7 | Copyright (c) 1998-2005 ILIAS open source, University of Cologne |
8 | |
9 | This program is free software; you can redistribute it and/or |
10 | modify it under the terms of the GNU General Public License |
11 | as published by the Free Software Foundation; either version 2 |
12 | of the License, or (at your option) any later version. |
13 | |
14 | This program is distributed in the hope that it will be useful, |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | GNU General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU General Public License |
20 | along with this program; if not, write to the Free Software |
21 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
22 +-----------------------------------------------------------------------------+
23*/
24
25require_once "./Services/Object/classes/class.ilObject.php";
26require_once "Services/WebDAV/classes/class.ilObjNull.php";
43{
44 private $table = 'dav_lock';
45
47 private $isDebug = false;
48
49 public function ilDAVLocks()
50 {
51 }
52
76 public function lockRef($refId, $iliasUserId, $davUser, $token, $expires, $depth, $scope)
77 {
78 $this->writelog('lockRef('.$refId.','.$iliasUserId.','.$davUser.','.$token.','.$expires.','.$depth.','.$scope.')');
79 global $tree, $txt;
80
81 $result = true;
82 $data = $tree->getNodeData($refId);
83
84 // Check whether a lock on the path to the object prevents the creation
85 // of a new lock
86 $locksOnPath = $this->getLocksOnPathRef($refId);
87
88 if ($scope == 'exclusive' && count($locksOnPath) > 0) {
89 $result = 'couldnt create exclusive lock due to existing lock on path '.var_export($locksOnPath,true);
90 }
91
92 foreach ($locksOnPath as $lock)
93 {
94 if ($lock['token'] == $token &&
95 $lock['obj_id'] == $data['obj_id'] &&
96 $lock['ilias_owner'] == $iliasUserId)
97 {
98 if ($this->updateLockWithoutCheckingObj($data['obj_id'], 0, $token, $expires))
99 {
100 return true;
101 }
102 else
103 {
104 return 'couldnt update lock';
105 }
106 }
107 }
108
109 if ($result === true)
110 {
111 foreach ($locksOnPath as $lock)
112 {
113 if ($lock['scope'] == 'exclusive' &&
114 ($lock['depth'] == 'infinity' || $lock['obj_id'] == $data['obj_id']) &&
115 $lock['ilias_owner'] != $iliasUserId)
116 {
117 $result = 'couldnt create lock due to exclusive lock on path '.var_export($lock,true);
118 break;
119 }
120 }
121 }
122
123 // Check whether a lock on the children (subtree) of the object prevents
124 // the creation of a new lock
125 if ($result === true && $depth == 'infinity')
126 {
127 // XXX - if lock has depth infinity, we must check for locks in the subtree
128 }
129
130 if ($result === true)
131 {
133 $data['obj_id'], 0,
134 $iliasUserId, $davUser, $token, $expires, $depth, $scope
135 );
136 }
137 return $result;
138 }
139
162 public function lockWithoutCheckingDAV(&$objDAV, $iliasUserId, $davUser, $token, $expires, $depth, $scope)
163 {
164 $objId = $objDAV->getObjectId();
165 $nodeId = $objDAV->getNodeId();
166
167 return $this->lockWithoutCheckingObj($objId, $nodeId, $iliasUserId, $davUser, $token, $expires, $depth, $scope);
168 }
193 public function lockWithoutCheckingObj($objId, $nodeId, $iliasUserId, $davUser, $token, $expires, $depth, $scope)
194 {
195 global $ilDB;
196
197 switch ($depth)
198 {
199 case 'infinity' : $depth = -1;
200 break;
201 case 0 :
202 $depth = 0;
203 break;
204 default :
205 trigger_error('invalid depth '.$depth,E_ERROR);
206 return;
207 }
208
209 switch ($scope)
210 {
211 case 'exclusive' : $scope = 'x'; break;
212 case 'shared' : $scope = 's'; break;
213 default : trigger_error('invalid scope '.$scope,E_ERROR); return;
214 }
215
216 $q = 'INSERT INTO '.$this->table
217 .' SET obj_id = '.$ilDB->quote($objId,'integer')
218 .', node_id = '.$ilDB->quote($nodeId,'integer')
219 .', ilias_owner = '.$ilDB->quote($iliasUserId,'text')
220 .', dav_owner = '.$ilDB->quote($davUser,'text')
221 .', token = '.$ilDB->quote($token,'text')
222 .', expires = '.$ilDB->quote($expires,'integer')
223 .', depth = '.$ilDB->quote($depth,'integer')
224 .', type = \'w\''
225 .', scope = '.$ilDB->quote($scope,'text')
226 ;
227 $this->writelog('lock query='.$q);
228 $result = $ilDB->manipulate($q);
229 return ! PEAR::isError($result);
230 }
242 public function updateLockWithoutCheckingDAV(&$objDAV, $token, $expires)
243 {
244 global $ilDB;
245 $objId = $objDAV->getObjectId();
246 $nodeId = $objDAV->getNodeId();
247
248 return $this->updateLockWithoutCheckingObj($objId, $nodeId, $token, $expires);
249 }
261 public function updateLockWithoutCheckingObj($objId, $nodeId, $token, $expires)
262 {
263 global $ilDB;
264
265 $q = 'UPDATE '.$this->table
266 .' SET expires = '.$ilDB->quote($expires,'integer')
267 .' WHERE token = '.$ilDB->quote($token,'text')
268 .' AND obj_id = '.$ilDB->quote($objId,'integer')
269 .' AND node_id = '.$ilDB->quote($nodeId,'integer')
270 ;
271 $aff = $ilDB->manipulate($q);
272 return $aff > 0;
273 }
285 public function unlockWithoutCheckingDAV(&$objDAV, $token)
286 {
287 global $ilDB;
288 $this->writelog('unlock('.$objDAV.','.$token.')');
289
290 $objId = $objDAV->getObjectId();
291 $nodeId = $objDAV->getNodeId();
292
293 // Unlock object
294 // FIXME - Maybe we should delete all rows with the same token, not
295 // just the ones with the same token, obj_id and node_id.
296 $q = 'DELETE FROM '.$this->table
297 .' WHERE token = '.$ilDB->quote($token,'text')
298 .' AND obj_id = '.$ilDB->quote($objId,'integer')
299 .' AND node_id = '.$ilDB->quote($nodeId,'integer')
300 ;
301 $this->writelog('unlock query='.$q);
302 $aff = $ilDB->manipulate($q);
303 $success = $aff > 0;
304
305 // clean up expired locks in 1 out of 100 unlock requests
306 if (rand(1,100) == 1)
307 {
308 $this->cleanUp();
309 }
310
311 return $success;
312 }
313
328 public function getLockDAV(&$objDAV,$token)
329 {
330 global $ilDB;
331 $this->writelog('getLocks('.$objDAV.')');
332 $objId = $objDAV->getObjectId();
333 $nodeId = $objDAV->getNodeId();
334
335 $q = 'SELECT ilias_owner, dav_owner, expires, depth, scope'
336 .' FROM '.$this->table
337 .' WHERE obj_id = '.$ilDB->quote($objId,'integer')
338 .' AND node_id = '.$ilDB->quote($nodeId,'integer')
339 .' AND token = '.$ilDB->quote($token,'text')
340 ;
341 $this->writelog('getLocks('.$objDAV.') query='.$q);
342 $r = $ilDB->query($q);
343
344 $result = array();
345 while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC))
346 {
347 if ($row['depth'] == -1) $row['depth'] = 'infinity';
348 $row['scope'] = ($row['scope'] == 'x') ? 'exclusive' : 'shared';
349 $row['token'] = $token;
350 $result = $row;
351 }
352 return $result;
353 }
368 public function getLocksOnObjectDAV(&$objDAV)
369 {
370 $objId = $objDAV->getObjectId();
371 $nodeId = $objDAV->getNodeId();
372
373 return $this->getLocksOnObjectObj($objId, $nodeId);
374 }
391 public function getLocksOnObjectObj($objId, $nodeId = 0)
392 {
393 global $ilDB;
394 $this->writelog('getLocks('.$objDAV.')');
395 $nodeId = 0;
396 $q = 'SELECT ilias_owner, dav_owner, token, expires, depth, scope'
397 .' FROM '.$this->table
398 .' WHERE obj_id = '.$ilDB->quote($objId,'integer')
399 .' AND node_id = '.$ilDB->quote($nodeId,'integer')
400 .' AND expires > '.$ilDB->quote(time(),'integer')
401 ;
402 $this->writelog('getLocks('.$objDAV.') query='.$q);
403 $r = $ilDB->query($q);
404
405 $result = array();
406 while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC))
407 {
408 if ($row['depth'] == -1) $row['depth'] = 'infinity';
409 $row['scope'] = ($row['scope'] == 'x') ? 'exclusive' : 'shared';
410 $result[] = $row;
411 }
412 return $result;
413 }
429 public function getLocksOnPathDAV(&$pathDAV)
430 {
431 global $ilDB;
432 $this->writelog('getLocksOnPathDAV');
433
434 $q = 'SELECT obj_id, node_id, ilias_owner, dav_owner, token, expires, depth, scope'
435 .' FROM '.$this->table
436 .' WHERE expires > '.$ilDB->quote(time(),'integer')
437 .' AND ('
438 ;
439 $isFirst = true;
440 foreach ($pathDAV as $objDAV)
441 {
442 $objId = $objDAV->getObjectId();
443 $nodeId = $objDAV->getNodeId();
444 if ($isFirst)
445 {
446 $isFirst = false;
447 } else {
448 $q .= ' OR ';
449 }
450 $q .= '(obj_id = '.$ilDB->quote($objId,'integer').' AND node_id = '.$ilDB->quote($nodeId,'integer').')';
451 }
452 $q .= ')';
453
454 $this->writelog('getLocksOnPathDAV('.$objDAV.') query='.$q);
455 $r = $ilDB->query($q);
456
457 $result = array();
458 while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC))
459 {
460 if ($row['depth'] == -1) $row['depth'] = 'infinity';
461 $row['scope'] = ($row['scope'] == 'x') ? 'exclusive' : 'shared';
462 $result[] = $row;
463 }
464 $this->writelog('getLocksOnPathDAV:'.var_export($result,true));
465 return $result;
466 }
482 public function getLocksOnPathRef($refId)
483 {
484 global $ilDB, $tree;
485 $this->writelog('getLocksOnPathRef('.$refId.')');
486
487 $pathFull = $tree->getPathFull($refId);
488
489 $q = 'SELECT obj_id, node_id, ilias_owner, dav_owner, token, expires, depth, scope'
490 .' FROM '.$this->table
491 .' WHERE expires > '.$ilDB->quote(time(),'integer')
492 .' AND ('
493 ;
494 $isFirst = true;
495 foreach ($pathFull as $pathItem)
496 {
497 $objId = $pathItem['obj_id'];
498 $nodeId = 0;
499 if ($isFirst)
500 {
501 $isFirst = false;
502 } else {
503 $q .= ' OR ';
504 }
505 $q .= '(obj_id = '.$ilDB->quote($objId,'integer').' AND node_id = '.$ilDB->quote($nodeId,'integer').')';
506 }
507 $q .= ')';
508
509 $this->writelog('getLocksOnPathRef('.$refId.') query='.$q);
510 $r = $ilDB->query($q);
511
512 $result = array();
513 while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC))
514 {
515 if ($row['depth'] == -1) $row['depth'] = 'infinity';
516 $row['scope'] = ($row['scope'] == 'x') ? 'exclusive' : 'shared';
517 $result[] = $row;
518 }
519 return $result;
520 }
526 public function cleanUp()
527 {
528 global $ilDB, $tree;
529
530 // 1. Get rid of locks that have expired over an hour ago
531 $old = time() - 3600;
532 $q = 'DELETE'
533 .' FROM '.$this->table
534 .' WHERE expires < '.$ilDB->quote($old,'integer')
535 ;
536 $ilDB->manipulate($q);
537
538 // 2. Get rid of null resources which are not associated to
539 // a lock due to step 1, or due to a database inconsistency
540 // because we are working with non-transactional tables
541 $q = 'SELECT dat.obj_id '
542 .' FROM object_data AS dat'
543 .' LEFT JOIN '.$this->table.' lck'
544 .' ON dat.obj_id = lck.obj_id'
545 .' WHERE dat.type = '.$ilDB->quote('null','text')
546 .' AND lck.obj_id IS NULL'
547 ;
548/* TODO: smeyer.' FOR UPDATE' */
549
550 $r = $ilDB->query($q);
551 while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC))
552 {
553 $references = ilObject::_getAllReferences($row['obj_id']);
554 $obj = new ilObjNull($row['obj_id'], false);
555 if (count($references) == 0)
556 {
557 $obj->delete();
558 } else {
559 foreach ($references as $refId)
560 {
561 $obj->setRefId($refId);
562 $obj->delete();
563 $nodeData = $tree->getNodeData($refId);
564 $tree->deleteTree($nodeData);
565 }
566 }
567 }
568 }
575 protected function writelog($message)
576 {
577 global $log, $ilias;
578 if ($this->isDebug)
579 {
580 $log->write(
581 $ilias->account->getLogin()
582 .' DAV ilDAVLocks.'.str_replace("\n",";",$message)
583 );
584 }
585 /*
586 if ($this->logFile)
587 {
588 $fh = fopen($this->logFile, 'a');
589 fwrite($fh, date('Y-m-d h:i:s '));
590 fwrite($fh, str_replace("\n",";",$message));
591 fwrite($fh, "\n\n");
592 fclose($fh);
593 }*/
594 }
595}
596// END WebDAV
597?>
$result
$success
Definition: Utf8Test.php:87
isError($data, $code=null)
Tell whether a value is a PEAR error.
Definition: PEAR.php:279
const DB_FETCHMODE_ASSOC
Definition: class.ilDB.php:10
updateLockWithoutCheckingObj($objId, $nodeId, $token, $expires)
Updates a write lock.
unlockWithoutCheckingDAV(&$objDAV, $token)
Discards a write lock.
lockWithoutCheckingDAV(&$objDAV, $iliasUserId, $davUser, $token, $expires, $depth, $scope)
Creates a write lock.
getLocksOnObjectObj($objId, $nodeId=0)
Returns all locks on the specified object id.
lockRef($refId, $iliasUserId, $davUser, $token, $expires, $depth, $scope)
Creates a lock an object, unless there are locks on the object or its parents, which prevent the crea...
$isDebug
Set this to true, to get debug output in the ILIAS log.
getLocksOnPathRef($refId)
Returns all locks on the specified object, specified by a reference id.
lockWithoutCheckingObj($objId, $nodeId, $iliasUserId, $davUser, $token, $expires, $depth, $scope)
cleanUp()
System maintenance: get rid of locks that have expired over an hour ago.
getLocksOnPathDAV(&$pathDAV)
Returns all locks on the specified object path.
updateLockWithoutCheckingDAV(&$objDAV, $token, $expires)
Updates a write lock.
writelog($message)
Writes a message to the logfile.,.
getLocksOnObjectDAV(&$objDAV)
Returns all locks on the specified object.
getLockDAV(&$objDAV, $token)
Returns the lock with the specified token on the specified DAV object.
static _getAllReferences($a_id)
get all reference ids of object
$txt
Definition: error.php:12
$data
$r
Definition: example_031.php:79
global $ilDB