1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
21:
22: if (!class_exists('File')) {
23: require LIBS . 'file.php';
24: }
25: 26: 27: 28: 29: 30: 31:
32: class FileEngine extends CacheEngine {
33:
34: 35: 36: 37: 38: 39:
40: var $_File = null;
41:
42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53:
54: var $settings = array();
55:
56: 57: 58: 59: 60: 61:
62: var $_init = true;
63:
64: 65: 66: 67: 68: 69: 70: 71: 72: 73:
74: function init($settings = array()) {
75: parent::init(array_merge(
76: array(
77: 'engine' => 'File', 'path' => CACHE, 'prefix'=> 'cake_', 'lock'=> false,
78: 'serialize'=> true, 'isWindows' => false
79: ),
80: $settings
81: ));
82: if (!isset($this->_File)) {
83: $this->_File =& new File($this->settings['path'] . DS . 'cake');
84: }
85:
86: if (DIRECTORY_SEPARATOR === '\\') {
87: $this->settings['isWindows'] = true;
88: }
89:
90: $path = $this->_File->Folder->cd($this->settings['path']);
91: if ($path) {
92: $this->settings['path'] = $path;
93: }
94: return $this->__active();
95: }
96:
97: 98: 99: 100: 101: 102:
103: function gc() {
104: return $this->clear(true);
105: }
106:
107: 108: 109: 110: 111: 112: 113: 114: 115:
116: function write($key, &$data, $duration) {
117: if ($data === '' || !$this->_init) {
118: return false;
119: }
120:
121: if ($this->_setKey($key) === false) {
122: return false;
123: }
124:
125: $lineBreak = "\n";
126:
127: if ($this->settings['isWindows']) {
128: $lineBreak = "\r\n";
129: }
130:
131: if (!empty($this->settings['serialize'])) {
132: if ($this->settings['isWindows']) {
133: $data = str_replace('\\', '\\\\\\\\', serialize($data));
134: } else {
135: $data = serialize($data);
136: }
137: }
138:
139: $expires = time() + $duration;
140: $contents = $expires . $lineBreak . $data . $lineBreak;
141: $old = umask(0);
142: $handle = fopen($this->_File->path, 'a');
143: umask($old);
144:
145: if (!$handle) {
146: return false;
147: }
148:
149: if ($this->settings['lock']) {
150: flock($handle, LOCK_EX);
151: }
152:
153: $success = ftruncate($handle, 0) && fwrite($handle, $contents) && fflush($handle);
154:
155: if ($this->settings['lock']) {
156: flock($handle, LOCK_UN);
157: }
158:
159: fclose($handle);
160: return $success;
161: }
162:
163: 164: 165: 166: 167: 168: 169:
170: function read($key) {
171: if ($this->_setKey($key) === false || !$this->_init || !$this->_File->exists()) {
172: return false;
173: }
174: if ($this->settings['lock']) {
175: $this->_File->lock = true;
176: }
177: $time = time();
178: $cachetime = intval($this->_File->read(11));
179:
180: if ($cachetime !== false && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) {
181: $this->_File->close();
182: return false;
183: }
184: $data = $this->_File->read(true);
185:
186: if ($data !== '' && !empty($this->settings['serialize'])) {
187: if ($this->settings['isWindows']) {
188: $data = str_replace('\\\\\\\\', '\\', $data);
189: }
190: $data = unserialize((string)$data);
191: }
192: $this->_File->close();
193: return $data;
194: }
195:
196: 197: 198: 199: 200: 201: 202:
203: function delete($key) {
204: if ($this->_setKey($key) === false || !$this->_init) {
205: return false;
206: }
207: return $this->_File->delete();
208: }
209:
210: 211: 212: 213: 214: 215: 216:
217: function clear($check) {
218: if (!$this->_init) {
219: return false;
220: }
221: $dir = dir($this->settings['path']);
222: if ($check) {
223: $now = time();
224: $threshold = $now - $this->settings['duration'];
225: }
226: $prefixLength = strlen($this->settings['prefix']);
227: while (($entry = $dir->read()) !== false) {
228: if (substr($entry, 0, $prefixLength) !== $this->settings['prefix']) {
229: continue;
230: }
231: if ($this->_setKey($entry) === false) {
232: continue;
233: }
234: if ($check) {
235: $mtime = $this->_File->lastChange();
236:
237: if ($mtime === false || $mtime > $threshold) {
238: continue;
239: }
240:
241: $expires = $this->_File->read(11);
242: $this->_File->close();
243:
244: if ($expires > $now) {
245: continue;
246: }
247: }
248: $this->_File->delete();
249: }
250: $dir->close();
251: return true;
252: }
253:
254: 255: 256: 257: 258: 259: 260:
261: function _setKey($key) {
262: $this->_File->Folder->cd($this->settings['path']);
263: if ($key !== $this->_File->name) {
264: $this->_File->name = $key;
265: $this->_File->path = null;
266: }
267: if (!$this->_File->Folder->inPath($this->_File->pwd(), true)) {
268: return false;
269: }
270: }
271:
272: 273: 274: 275: 276: 277:
278: function __active() {
279: if ($this->_init && !is_writable($this->settings['path'])) {
280: $this->_init = false;
281: trigger_error(sprintf(__('%s is not writable', true), $this->settings['path']), E_USER_WARNING);
282: return false;
283: }
284: return true;
285: }
286: }
287: