1: <?php
2: /**
3: * This file contains the the static file handler class.
4: *
5: * @package Core
6: * @subpackage Util
7: * @version SVN Revision $Rev:$
8: *
9: * @author Mischa Holz
10: * @copyright four for business AG <www.4fb.de>
11: * @license http://www.contenido.org/license/LIZENZ.txt
12: * @link http://www.4fb.de
13: * @link http://www.contenido.org
14: */
15: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
16:
17: /**
18: * Class for file handling.
19: * Provides functions for dealing with files.
20: *
21: * @package Core
22: * @subpackage Util
23: */
24: class cFileHandler {
25:
26: /**
27: * Creates a new file
28: *
29: * @param string $filename the name and path of the new file
30: * @param string $content optional content of the new file. Optional.
31: * @return bool true on success. Otherwise false.
32: */
33: public static function create($filename, $content = '') {
34: $success = file_put_contents($filename, $content) === strlen($content);
35: if ($success) {
36: self::setDefaultFilePerms($filename);
37: }
38:
39: return $success;
40: }
41:
42: /**
43: * Reads bytes from a file
44: *
45: * @param string $filename the name and path of the file
46: * @param int $length the number of bytes to read. Optional.
47: * @param int $offset this will be the first byte which is read. Optional.
48: * @param bool $reverse if true, the function will start from the back of
49: * the file. Optional.
50: * @throws cInvalidArgumentException if the file with the given filename
51: * does not exist
52: * @return string bool success it returns the bytes which have been read.
53: * Otherwise false.
54: */
55: public static function read($filename, $length = 0, $offset = 0, $reverse = false) {
56: if (!cFileHandler::exists($filename)) {
57: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
58: }
59:
60: if ($reverse) {
61: return file_get_contents($filename, false, NULL, filesize($filename) - $length - $offset, $length);
62: } else if ($length > 0 && $offset == 0) {
63: return file_get_contents($filename, false, NULL, 0, $length);
64: } else if ($offset > 0 && $length == 0) {
65: return file_get_contents($filename, false, NULL, $offset);
66: } else if ($offset > 0 && $length > 0) {
67: return file_get_contents($filename, false, NULL, $offset, $length);
68: } else {
69: return file_get_contents($filename);
70: }
71: }
72:
73: /**
74: * Reads a file line by line
75: *
76: * @param string $filename the name and path of the file
77: * @param int $lines the number of lines to be read. Optional.
78: * @param int $lineoffset this will be the first line which is read.
79: * Optional.
80: * @throws cInvalidArgumentException if the file with the given filename
81: * does not exist
82: * @return string array bool one line was read the function will return it.
83: * If more than one line was read the function will return an array
84: * containing the lines. Otherwise false is returned
85: */
86: public static function readLine($filename, $lines = 0, $lineoffset = 0) {
87: if (!cFileHandler::exists($filename)) {
88: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
89: }
90:
91: $f = fopen($filename, 'r');
92:
93: if ($f === false) {
94: fclose($f);
95: return false;
96: }
97: if ($lines == 0) {
98: $lines = 1;
99: }
100:
101: for ($i = 0; $i < $lineoffset; $i++) {
102: $waste = fgets($f);
103: }
104:
105: $ret = NULL;
106: if ($lines > 1) {
107: $ret = array();
108: for ($i = 0; $i < $lines; $i++) {
109: $temp = fgets($f);
110: if ($temp === false) {
111: fclose($f);
112: return false;
113: }
114: $ret[] = substr($temp, 0, strlen($temp) - 1);
115: }
116: } else {
117: $ret = fgets($f);
118: $ret = substr($ret, 0, strlen($ret) - 1);
119: }
120:
121: fclose($f);
122: return $ret;
123: }
124:
125: /**
126: * Writes data to a file
127: *
128: * @param string $filename the name and path of the file
129: * @param string $content the data which should be written
130: * @param bool $append if true the data will be appended to the file.
131: * Optional.
132: * @return bool true on success, false otherwise
133: */
134: public static function write($filename, $content, $append = false) {
135: $flag = 0;
136: if ($append && self::exists($filename)) {
137: $flag = FILE_APPEND;
138: }
139:
140: $success = file_put_contents($filename, $content, $flag);
141: if ((int) $success != 0) {
142: self::setDefaultFilePerms($filename);
143: }
144:
145: return !($success === false);
146: }
147:
148: /**
149: * Writes a line to a file (this is similar to
150: * cFileHandler::write($filename, $data."\n", $apppend)
151: *
152: * @see cFileHandler::write($filename, $content, $append)
153: * @param string $filename the name and path to the file
154: * @param string $content the data of the line
155: * @param bool $append if true the data will be appended to file. Optional.
156: * @return bool true on success, false otherwise
157: */
158: public static function writeLine($filename, $content, $append = false) {
159: return self::write($filename, $content . "\n", $append);
160: }
161:
162: /**
163: * Checks if a file exists
164: *
165: * @param string $filename the name and path of the file
166: * @return bool true if the file exists
167: */
168: public static function exists($filename) {
169: return file_exists($filename);
170: }
171:
172: /**
173: * Checks if the file is writable for the PHP user
174: *
175: * @param string $filename the name and path of the file
176: * @return bool true if the file can be written
177: */
178: public static function writeable($filename) {
179: return is_writable($filename);
180: }
181:
182: /**
183: * Checks if a file is readable for the PHP user
184: *
185: * @param string $filename the name and path of the file
186: * @throws cInvalidArgumentException if the file with the given filename
187: * does not exist
188: * @return bool true if the file is readable
189: */
190: public static function readable($filename) {
191: if (!cFileHandler::exists($filename)) {
192: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
193: }
194:
195: return is_readable($filename);
196: }
197:
198: /**
199: * Removes a file from the filesystem
200: *
201: * @param string $filename the name and path of the file
202: * @throws cInvalidArgumentException if the file with the given filename
203: * does not exist
204: * @return bool true on success
205: */
206: public static function remove($filename) {
207: if (!cFileHandler::exists($filename)) {
208: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
209: }
210:
211: return unlink($filename);
212: }
213:
214: /**
215: * Truncates a file so that it is empty
216: *
217: * @param string $filename the name and path of the file
218: * @throws cInvalidArgumentException if the file with the given filename
219: * does not exist
220: * @return bool true on success
221: */
222: public static function truncate($filename) {
223: if (!cFileHandler::exists($filename)) {
224: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
225: }
226: $success = file_put_contents($filename, '') === 0;
227: if ($success) {
228: self::setDefaultFilePerms($filename);
229: }
230:
231: return $success;
232: }
233:
234: /**
235: * Moves a file
236: *
237: * @param string $filename the name of the source file
238: * @param string $destination the destination. Note that the file can also
239: * be renamed in the process of moving it
240: * @throws cInvalidArgumentException if the file with the given filename
241: * does not exist
242: * @return bool true on success
243: */
244: public static function move($filename, $destination) {
245: if (!cFileHandler::exists($filename)) {
246: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
247: }
248: $success = rename($filename, $destination);
249: if ($success) {
250: self::setDefaultFilePerms($destination);
251: }
252:
253: return $success;
254: }
255:
256: /**
257: * Renames a file
258: *
259: * @param string $filename the name and path of the file
260: * @param string $new_filename the new name of the file
261: * @throws cInvalidArgumentException if the file with the given filename
262: * does not exist
263: * @return bool true on success
264: */
265: public static function rename($filename, $new_filename) {
266: if (!cFileHandler::exists($filename)) {
267: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
268: }
269: $success = rename($filename, dirname($filename) . '/' . $new_filename);
270: if ($success) {
271: self::setDefaultFilePerms(dirname($filename) . '/' . $new_filename);
272: }
273:
274: return $success;
275: }
276:
277: /**
278: * Copies a file
279: *
280: * @param string $filename the name and path of the file
281: * @param string $destination the destination. Note that existing files get
282: * overwritten
283: * @throws cInvalidArgumentException if the file with the given filename
284: * does not exist
285: * @return bool true on success
286: */
287: public static function copy($filename, $destination) {
288: if (!cFileHandler::exists($filename)) {
289: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
290: }
291: $success = copy($filename, $destination);
292: if ($success) {
293: self::setDefaultFilePerms($destination);
294: }
295:
296: return $success;
297: }
298:
299: /**
300: * Changes the file permissions
301: *
302: * @param string $filename the name and path of the file
303: * @param int $mode the new access mode : php chmod needs octal value
304: * @throws cInvalidArgumentException if the file with the given filename
305: * does not exist
306: * @return bool true on success
307: */
308: public static function chmod($filename, $mode) {
309: if (!cFileHandler::exists($filename)) {
310: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
311: }
312: // chmod needs octal value for correct execution.
313: $mode = intval($mode, 8);
314: return chmod($filename, $mode);
315: }
316:
317: /**
318: * Returns an array containing information about the file.
319: * Currently
320: * following elements are in it: 'size' - the file size (in byte) 'atime' -
321: * the time the file was last accessed (unix timestamp) 'ctime' - time the
322: * file was created (unix timestamp) 'mtime' - time the file was last
323: * modified (unix timestamp) 'perms' - permissions of the file represented
324: * in 4 octal digits 'extension' - the file extension or '' if there's no
325: * extension 'mime' - the mime type of the file
326: *
327: * @param string $filename the name and path to the file
328: * @throws cInvalidArgumentException if the file with the given filename
329: * does not exist
330: * @return array Returns an array containing information about the file
331: */
332: public static function info($filename) {
333: if (!cFileHandler::exists($filename)) {
334: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
335: }
336:
337: $ret = array();
338:
339: $ret['size'] = @filesize($filename);
340: $ret['atime'] = @fileatime($filename);
341: $ret['ctime'] = @filectime($filename);
342: $ret['mtime'] = @filemtime($filename);
343:
344: $temp = @decoct(fileperms($filename));
345: $ret['perms'] = substr($temp, strlen($temp) - 4);
346:
347: $ret['extension'] = substr(basename($filename), (int) strrpos(basename($filename), '.') + 1);
348: if ($ret['extension'] == basename($filename)) {
349: $ret['extension'] = '';
350: }
351:
352: if (version_compare(PHP_VERSION, '5.3', '<') && function_exists('mime_content_type')) {
353: // function is deprecated in PHP 5.3
354: $ret['mime'] = @mime_content_type($filename);
355: } else if (function_exists('finfo_open')) {
356: // extension has to be installed seperately in versions prior to 5.3
357: $finfo = @finfo_open(FILEINFO_MIME_TYPE);
358: $ret['mime'] = @finfo_file($finfo, $filename);
359: } else {
360: $ret['mime'] = '';
361: }
362:
363: return $ret;
364: }
365:
366: /**
367: * Returns the extension of passed filename
368: *
369: * @param string $basename
370: * @return string
371: */
372: public static function getExtension($basename) {
373: $aFileName = explode('.', trim($basename, '.'));
374:
375: return (count($aFileName) > 1) ? $aFileName[count($aFileName) - 1] : '';
376: }
377:
378: /**
379: * Sets the default file permissions on the given file.
380: *
381: * @param string $filename the name of the file
382: * @return boolean true on success or false on failure
383: */
384: public static function setDefaultFilePerms($filename) {
385: $cfg = cRegistry::getConfig();
386:
387: if (isset($cfg['default_perms']['file']) === false) {
388: return false;
389: }
390:
391: $filePerms = $cfg['default_perms']['file'];
392: return cFileHandler::chmod($filename, $filePerms);
393: }
394:
395: /**
396: *
397: * @see cDirHandler::recursiveRmdir()
398: * @deprecated 2013-11-11 - Use the class cDirHandler instead.
399: */
400: public static function recursiveRmdir($dirname) {
401: cDeprecated("Use the class cDirHandler instead.");
402: return cDirHandler::recursiveRmdir($dirname);
403: }
404:
405: /**
406: *
407: * @see cDirHandler::recursiveCopy()
408: * @deprecated 2013-11-11 - Use the class cDirHandler instead.
409: */
410: public static function recursiveCopy($filename, $destination) {
411: cDeprecated("Use the class cDirHandler instead.");
412: return cDirHandler::recursiveCopy($filename, $destination);
413: }
414:
415: /**
416: *
417: * @see cDirHandler::isDirectoryEmpty()
418: * @deprecated 2013-11-11 - Use the class cDirHandler instead.
419: */
420: public static function isDirectoryEmpty($dir) {
421: cDeprecated("Use the class cDirHandler instead.");
422: return cDirHandler::isDirectoryEmpty($dir);
423: }
424:
425: /**
426: *
427: * @see cDirHandler::setDefaultDirPerms()
428: * @deprecated 2013-11-11 - Use the class cDirHandler instead.
429: */
430: public static function setDefaultDirPerms($dirname) {
431: cDeprecated("Use the class cDirHandler instead.");
432: return cDirHandler::setDefaultDirPerms($dirname);
433: }
434:
435: /**
436: * Validates the given filename.
437: *
438: * @param string $filename the filename to validate
439: * @param bool $notifyAndExitOnFailure if set, function will show a
440: * notification and will exit the script
441: * @return bool true if the given filename is valid, false otherwise
442: */
443: public static function validateFilename($filename, $notifyAndExitOnFailure = true) {
444: // check if filename only contains valid characters
445: if (preg_match('/[^a-z0-9._-]/i', $filename)) {
446: // validation failure...
447: if ($notifyAndExitOnFailure) {
448: // display notification and exit
449: cRegistry::addErrorMessage(i18n('Wrong file name.'));
450: $page = new cGuiPage('generic_page');
451: $page->abortRendering();
452: $page->render();
453: exit();
454: }
455:
456: return false;
457: }
458:
459: // check if filename is empty
460: if (strlen(trim($filename)) == 0) {
461: // validation failure...
462: if ($notifyAndExitOnFailure) {
463: // display notification and exit
464: $notification = new cGuiNotification();
465: $notification->displayNotification("error", i18n("Please insert file name."));
466: exit();
467: }
468:
469: return false;
470: }
471:
472: return true;
473: }
474:
475: /**
476: * Check if given filename is either '.' or '..'.
477: *
478: * @param string $fileName
479: * @return boolean
480: */
481: public static function fileNameIsDot($fileName) {
482: if ($fileName != '.' && $fileName != '..') {
483: return false;
484: } else {
485: return true;
486: }
487: }
488:
489: }
490: