1<?php 2 3namespace Sabre\DAV\Locks\Backend; 4 5use Sabre\DAV\Locks\LockInfo; 6 7/** 8 * This Locks backend stores all locking information in a single file. 9 * 10 * Note that this is not nearly as robust as a database. If you are considering 11 * using this backend, keep in mind that the PDO backend can work with SqLite, 12 * which is designed to be a good file-based database. 13 * 14 * It literally solves the problem this class solves as well, but much better. 15 * 16 * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/). 17 * @author Evert Pot (http://evertpot.com/) 18 * @license http://sabre.io/license/ Modified BSD License 19 */ 20class File extends AbstractBackend { 21 22 /** 23 * The storage file 24 * 25 * @var string 26 */ 27 private $locksFile; 28 29 /** 30 * Constructor 31 * 32 * @param string $locksFile path to file 33 */ 34 function __construct($locksFile) { 35 36 $this->locksFile = $locksFile; 37 38 } 39 40 /** 41 * Returns a list of Sabre\DAV\Locks\LockInfo objects 42 * 43 * This method should return all the locks for a particular uri, including 44 * locks that might be set on a parent uri. 45 * 46 * If returnChildLocks is set to true, this method should also look for 47 * any locks in the subtree of the uri for locks. 48 * 49 * @param string $uri 50 * @param bool $returnChildLocks 51 * @return array 52 */ 53 function getLocks($uri, $returnChildLocks) { 54 55 $newLocks = []; 56 57 $locks = $this->getData(); 58 59 foreach ($locks as $lock) { 60 61 if ($lock->uri === $uri || 62 //deep locks on parents 63 ($lock->depth != 0 && strpos($uri, $lock->uri . '/') === 0) || 64 65 // locks on children 66 ($returnChildLocks && (strpos($lock->uri, $uri . '/') === 0))) { 67 68 $newLocks[] = $lock; 69 70 } 71 72 } 73 74 // Checking if we can remove any of these locks 75 foreach ($newLocks as $k => $lock) { 76 if (time() > $lock->timeout + $lock->created) unset($newLocks[$k]); 77 } 78 return $newLocks; 79 80 } 81 82 /** 83 * Locks a uri 84 * 85 * @param string $uri 86 * @param LockInfo $lockInfo 87 * @return bool 88 */ 89 function lock($uri, LockInfo $lockInfo) { 90 91 // We're making the lock timeout 30 minutes 92 $lockInfo->timeout = 1800; 93 $lockInfo->created = time(); 94 $lockInfo->uri = $uri; 95 96 $locks = $this->getData(); 97 98 foreach ($locks as $k => $lock) { 99 if ( 100 ($lock->token == $lockInfo->token) || 101 (time() > $lock->timeout + $lock->created) 102 ) { 103 unset($locks[$k]); 104 } 105 } 106 $locks[] = $lockInfo; 107 $this->putData($locks); 108 return true; 109 110 } 111 112 /** 113 * Removes a lock from a uri 114 * 115 * @param string $uri 116 * @param LockInfo $lockInfo 117 * @return bool 118 */ 119 function unlock($uri, LockInfo $lockInfo) { 120 121 $locks = $this->getData(); 122 foreach ($locks as $k => $lock) { 123 124 if ($lock->token == $lockInfo->token) { 125 126 unset($locks[$k]); 127 $this->putData($locks); 128 return true; 129 130 } 131 } 132 return false; 133 134 } 135 136 /** 137 * Loads the lockdata from the filesystem. 138 * 139 * @return array 140 */ 141 protected function getData() { 142 143 if (!file_exists($this->locksFile)) return []; 144 145 // opening up the file, and creating a shared lock 146 $handle = fopen($this->locksFile, 'r'); 147 flock($handle, LOCK_SH); 148 149 // Reading data until the eof 150 $data = stream_get_contents($handle); 151 152 // We're all good 153 flock($handle, LOCK_UN); 154 fclose($handle); 155 156 // Unserializing and checking if the resource file contains data for this file 157 $data = unserialize($data); 158 if (!$data) return []; 159 return $data; 160 161 } 162 163 /** 164 * Saves the lockdata 165 * 166 * @param array $newData 167 * @return void 168 */ 169 protected function putData(array $newData) { 170 171 // opening up the file, and creating an exclusive lock 172 $handle = fopen($this->locksFile, 'a+'); 173 flock($handle, LOCK_EX); 174 175 // We can only truncate and rewind once the lock is acquired. 176 ftruncate($handle, 0); 177 rewind($handle); 178 179 fwrite($handle, serialize($newData)); 180 flock($handle, LOCK_UN); 181 fclose($handle); 182 183 } 184 185} 186