Overview

Packages

  • Vfs

Classes

  • Horde_Vfs
  • Horde_Vfs_Base
  • Horde_Vfs_Browser
  • Horde_Vfs_Exception
  • Horde_Vfs_File
  • Horde_Vfs_Ftp
  • Horde_Vfs_Gc
  • Horde_Vfs_Horde
  • Horde_Vfs_Kolab
  • Horde_Vfs_ListItem
  • Horde_Vfs_Musql
  • Horde_Vfs_Object
  • Horde_Vfs_Smb
  • Horde_Vfs_Sql
  • Horde_Vfs_SqlFile
  • Horde_Vfs_Ssh2
  • Horde_Vfs_Translation
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * VFS API for abstracted file storage and access.
  4:  *
  5:  * Copyright 2002-2012 Horde LLC (http://www.horde.org/)
  6:  *
  7:  * See the enclosed file COPYING for license information (LGPL). If you
  8:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  9:  *
 10:  * @author  Chuck Hagenbuch <chuck@horde.org>
 11:  * @package Vfs
 12:  */
 13: abstract class Horde_Vfs_Base
 14: {
 15:     /**
 16:      * Hash containing connection parameters.
 17:      *
 18:      * @var array
 19:      */
 20:     protected $_params = array();
 21: 
 22:     /**
 23:      * List of additional credentials required for this VFS backend (example:
 24:      * For FTP, we need a username and password to log in to the server with).
 25:      *
 26:      * @var array
 27:      */
 28:     protected $_credentials = array();
 29: 
 30:     /**
 31:      * List of permissions and if they can be changed in this VFS backend.
 32:      *
 33:      * @var array
 34:      */
 35:     protected $_permissions = array(
 36:         'owner' => array(
 37:             'read' => false,
 38:             'write' => false,
 39:             'execute' => false
 40:         ),
 41:         'group' => array(
 42:             'read' => false,
 43:             'write' => false,
 44:             'execute' => false
 45:         ),
 46:         'all' => array(
 47:             'read' => false,
 48:             'write' => false,
 49:             'execute' => false
 50:         )
 51:     );
 52: 
 53:     /**
 54:      * The current size, in bytes, of the VFS tree.
 55:      *
 56:      * @var integer
 57:      */
 58:     protected $_vfsSize = null;
 59: 
 60:     /**
 61:      * Constructor.
 62:      *
 63:      * @param array $params  A hash containing connection parameters.
 64:      */
 65:     public function __construct($params = array())
 66:     {
 67:         $this->setParams(array(
 68:             'user' => '',
 69:             'vfs_quotalimit' => -1,
 70:             'vfs_quotaroot' => ''
 71:         ));
 72:         $this->setParams($params);
 73:     }
 74: 
 75:     /**
 76:      * Checks the credentials that we have by calling _connect(), to see if
 77:      * there is a valid login.
 78:      *
 79:      * @throws Horde_Vfs_Exception
 80:      */
 81:     public function checkCredentials()
 82:     {
 83:         $this->_connect();
 84:     }
 85: 
 86:     /**
 87:      * TODO
 88:      *
 89:      * @throws Horde_Vfs_Exception
 90:      */
 91:     protected function _connect()
 92:     {
 93:     }
 94: 
 95:     /**
 96:      * Sets configuration parameters.
 97:      *
 98:      * @param array $params  An associative array with parameter names as
 99:      *                       keys.
100:      */
101:     public function setParams($params = array())
102:     {
103:         $this->_params = array_merge($this->_params, $params);
104:     }
105: 
106:     /**
107:      * Returns configuration parameters.
108:      *
109:      * @param string $name  The parameter to return.
110:      *
111:      * @return mixed  The parameter value or null if it doesn't exist.
112:      */
113:     public function getParam($name)
114:     {
115:         return isset($this->_params[$name])
116:             ? $this->_params[$name]
117:             : null;
118:     }
119: 
120:     /**
121:      * Retrieves the size of a file from the VFS.
122:      *
123:      * @abstract
124:      *
125:      * @param string $path  The pathname to the file.
126:      * @param string $name  The filename to retrieve.
127:      *
128:      * @return integer  The file size.
129:      * @throws Horde_Vfs_Exception
130:      */
131:     public function size($path, $name)
132:     {
133:         throw new Horde_Vfs_Exception('Not supported.');
134:     }
135: 
136:     /**
137:      * Returns the size of a folder
138:      *
139:      * @param string $path  The path to the folder.
140:      * @param string $name  The name of the folder.
141:      *
142:      * @return integer  The size of the folder, in bytes.
143:      * @throws Horde_Vfs_Exception
144:      */
145:     public function getFolderSize($path = null, $name = null)
146:     {
147:         $size = 0;
148:         $root = (!is_null($path) ? $path . '/' : '') . $name;
149:         $object_list = $this->listFolder($root, null, true, false, true);
150: 
151:         foreach ($object_list as $key => $val) {
152:             $size += isset($val['subdirs'])
153:                 ? $this->getFolderSize($root, $key)
154:                 : $this->size($root, $key);
155:         }
156: 
157:         return $size;
158:     }
159: 
160:     /**
161:      * Retrieves a file from the VFS.
162:      *
163:      * @abstract
164:      *
165:      * @param string $path  The pathname to the file.
166:      * @param string $name  The filename to retrieve.
167:      *
168:      * @return string  The file data.
169:      * @throws Horde_Vfs_Exception
170:      */
171:     public function read($path, $name)
172:     {
173:         throw new Horde_Vfs_Exception('Not supported.');
174:     }
175: 
176:     /**
177:      * Retrieves a file from the VFS as an on-disk local file.
178:      *
179:      * This function provides a file on local disk with the data of a VFS file
180:      * in it. This file <em>cannot</em> be modified! The behavior if you do
181:      * modify it is undefined. It will be removed at the end of the request.
182:      *
183:      * @param string $path  The pathname to the file.
184:      * @param string $name  The filename to retrieve.
185:      *
186:      * @return string  A local filename.
187:      * @throws Horde_Vfs_Exception
188:      */
189:     public function readFile($path, $name)
190:     {
191:         // Create a temporary file and register it for deletion at the
192:         // end of this request.
193:         if (!($localFile = Horde_Util::getTempFile('vfs'))) {
194:             throw new Horde_Vfs_Exception('Unable to create temporary file.');
195:         }
196: 
197:         if (is_callable(array($this, 'readStream'))) {
198:             // Use a stream from the VFS if possible, to avoid reading all data
199:             // into memory.
200:             $stream = $this->readStream($path, $name);
201: 
202:             if (!($localStream = fopen($localFile, 'w'))) {
203:                 throw new Horde_Vfs_Exception('Unable to open temporary file.');
204:             }
205:             stream_copy_to_stream($stream, $localStream);
206:             fclose($localStream);
207:         } else {
208:             // We have to read all of the data in one shot.
209:             $data = $this->read($path, $name);
210:             file_put_contents($localFile, $data);
211:         }
212: 
213:         // $localFile now has $path/$name's data in it.
214:         return $localFile;
215:     }
216: 
217:     /**
218:      * Retrieves a part of a file from the VFS. Particularly useful when
219:      * reading large files which would exceed the PHP memory limits if they
220:      * were stored in a string.
221:      *
222:      * @abstract
223:      *
224:      * @param string  $path       The pathname to the file.
225:      * @param string  $name       The filename to retrieve.
226:      * @param integer $offset     The offset of the part. (The new offset will
227:      *                            be stored in here).
228:      * @param integer $length     The length of the part. If the length = -1,
229:      *                            the whole part after the offset is retrieved.
230:      *                            If more bytes are given as exists after the
231:      *                            given offset. Only the available bytes are
232:      *                            read.
233:      * @param integer $remaining  The bytes that are left, after the part that
234:      *                            is retrieved.
235:      *
236:      * @return string  The file data.
237:      * @throws Horde_Vfs_Exception
238:      */
239:     public function readByteRange($path, $name, &$offset, $length, &$remaining)
240:     {
241:         throw new Horde_Vfs_Exception('Not supported.');
242:     }
243: 
244:     /**
245:      * Stores a file in the VFS.
246:      *
247:      * @abstract
248:      *
249:      * @param string $path         The path to store the file in.
250:      * @param string $name         The filename to use.
251:      * @param string $tmpFile      The temporary file containing the data to
252:      *                             be stored.
253:      * @param boolean $autocreate  Automatically create directories?
254:      *
255:      * @throws Horde_Vfs_Exception
256:      */
257:     public function write($path, $name, $tmpFile, $autocreate = false)
258:     {
259:         throw new Horde_Vfs_Exception('Not supported.');
260:     }
261: 
262:     /**
263:      * Stores a file in the VFS from raw data.
264:      *
265:      * @abstract
266:      *
267:      * @param string $path         The path to store the file in.
268:      * @param string $name         The filename to use.
269:      * @param string $data         The file data.
270:      * @param boolean $autocreate  Automatically create directories?
271:      *
272:      * @throws Horde_Vfs_Exception
273:      */
274:     public function writeData($path, $name, $data, $autocreate = false)
275:     {
276:         throw new Horde_Vfs_Exception('Not supported.');
277:     }
278: 
279:     /**
280:      * Moves a file through the backend.
281:      *
282:      * @param string $path         The path of the original file.
283:      * @param string $name         The name of the original file.
284:      * @param string $dest         The destination file name.
285:      * @param boolean $autocreate  Automatically create directories?
286:      *
287:      * @throws Horde_Vfs_Exception
288:      */
289:     public function move($path, $name, $dest, $autocreate = false)
290:     {
291:         $this->copy($path, $name, $dest, $autocreate);
292:         $this->deleteFile($path, $name);
293:     }
294: 
295:     /**
296:      * Copies a file through the backend.
297:      *
298:      * @param string $path         The path of the original file.
299:      * @param string $name         The name of the original file.
300:      * @param string $dest         The name of the destination directory.
301:      * @param boolean $autocreate  Automatically create directories?
302:      *
303:      * @throws Horde_Vfs_Exception
304:      */
305:     public function copy($path, $name, $dest, $autocreate = false)
306:     {
307:         $orig = $this->_getPath($path, $name);
308:         if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) {
309:             throw new Horde_Vfs_Exception('Cannot copy file(s) - source and destination are the same.');
310:         }
311: 
312:         if ($autocreate) {
313:             $this->autocreatePath($dest);
314:         }
315: 
316:         if ($this->isFolder($path, $name)) {
317:             $this->_copyRecursive($path, $name, $dest);
318:         } else {
319:             $this->writeData($dest, $name, $this->read($path, $name), $autocreate);
320:         }
321:     }
322: 
323:     /**
324:      * Recursively copies a directory through the backend.
325:      *
326:      * @param string $path  The path of the original file.
327:      * @param string $name  The name of the original file.
328:      * @param string $dest  The name of the destination directory.
329:      *
330:      * @throws Horde_Vfs_Exception
331:      */
332:     protected function _copyRecursive($path, $name, $dest)
333:     {
334:         $this->createFolder($dest, $name);
335: 
336:         $file_list = $this->listFolder($this->_getPath($path, $name));
337:         foreach ($file_list as $file) {
338:             $this->copy($this->_getPath($path, $name), $file['name'], $this->_getPath($dest, $name));
339:         }
340:     }
341: 
342:     /**
343:      * Alias to deleteFile()
344:      */
345:     public function delete($path, $name)
346:     {
347:         return $this->deleteFile($path, $name);
348:     }
349: 
350:     /**
351:      * Deletes a file from the VFS.
352:      *
353:      * @abstract
354:      *
355:      * @param string $path  The path to delete the file from.
356:      * @param string $name  The filename to delete.
357:      *
358:      * @throws Horde_Vfs_Exception
359:      */
360:     public function deleteFile($path, $name)
361:     {
362:         throw new Horde_Vfs_Exception('Not supported.');
363:     }
364: 
365:     /**
366:      * Renames a file in the VFS.
367:      *
368:      * @abstract
369:      *
370:      * @param string $oldpath  The old path to the file.
371:      * @param string $oldname  The old filename.
372:      * @param string $newpath  The new path of the file.
373:      * @param string $newname  The new filename.
374:      *
375:      * @throws Horde_Vfs_Exception
376:      */
377:     public function rename($oldpath, $oldname, $newpath, $newname)
378:     {
379:         throw new Horde_Vfs_Exception('Not supported.');
380:     }
381: 
382:     /**
383:      * Returns if a given file or folder exists in a folder.
384:      *
385:      * @param string $path  The path to the folder.
386:      * @param string $name  The file or folder name.
387:      *
388:      * @return boolean  True if it exists, false otherwise.
389:      */
390:     public function exists($path, $name)
391:     {
392:         try {
393:             $list = $this->listFolder($path);
394:             return isset($list[$name]);
395:         } catch (Horde_Vfs_Exception $e) {
396:             return false;
397:         }
398:     }
399: 
400:     /**
401:      * Creates a folder in the VFS.
402:      *
403:      * @abstract
404:      *
405:      * @param string $path  The parent folder.
406:      * @param string $name  The name of the new folder.
407:      *
408:      * @throws Horde_Vfs_Exception
409:      */
410:     public function createFolder($path, $name)
411:     {
412:         throw new Horde_Vfs_Exception('Not supported.');
413:     }
414: 
415:     /**
416:      * Automatically creates any necessary parent directories in the specified
417:      * $path.
418:      *
419:      * @param string $path  The VFS path to autocreate.
420:      *
421:      * @throws Horde_Vfs_Exception
422:      */
423:     public function autocreatePath($path)
424:     {
425:         $dirs = explode('/', $path);
426:         if (is_array($dirs)) {
427:             $cur = '/';
428:             foreach ($dirs as $dir) {
429:                 if (!strlen($dir)) {
430:                     continue;
431:                 }
432:                 if (!$this->isFolder($cur, $dir)) {
433:                     $result = $this->createFolder($cur, $dir);
434:                 }
435:                 if ($cur != '/') {
436:                     $cur .= '/';
437:                 }
438:                 $cur .= $dir;
439:             }
440:         }
441:     }
442: 
443:     /**
444:      * Checks if a given item is a folder.
445:      *
446:      * @param string $path  The parent folder.
447:      * @param string $name  The item name.
448:      *
449:      * @return boolean  True if it is a folder, false otherwise.
450:      */
451:     public function isFolder($path, $name)
452:     {
453:         try {
454:             $folderList = $this->listFolder($path, null, true, true);
455:             return isset($folderList[$name]);
456:         } catch (Horde_Vfs_Exception $e) {
457:             return false;
458:         }
459:     }
460: 
461:     /**
462:      * Deletes a folder from the VFS.
463:      *
464:      * @abstract
465:      *
466:      * @param string $path        The parent folder.
467:      * @param string $name        The name of the folder to delete.
468:      * @param boolean $recursive  Force a recursive delete?
469:      *
470:      * @throws Horde_Vfs_Exception
471:      */
472:     public function deleteFolder($path, $name, $recursive = false)
473:     {
474:         throw new Horde_Vfs_Exception('Not supported.');
475:     }
476: 
477:     /**
478:      * Recursively remove all files and subfolders from the given
479:      * folder.
480:      *
481:      * @param string $path  The path of the folder to empty.
482:      *
483:      * @throws Horde_Vfs_Exception
484:      */
485:     public function emptyFolder($path)
486:     {
487:         // Get and delete the subfolders.
488:         foreach ($this->listFolder($path, null, true, true) as $folder) {
489:             $this->deleteFolder($path, $folder['name'], true);
490:         }
491: 
492:         // Only files are left, get and delete them.
493:         foreach ($this->listFolder($path) as $file) {
494:             $this->deleteFile($path, $file['name']);
495:         }
496:     }
497: 
498:     /**
499:      * Returns a file list of the directory passed in.
500:      *
501:      * @param string $path        The path of the directory.
502:      * @param mixed $filter       String/hash to filter file/dirname on.
503:      * @param boolean $dotfiles   Show dotfiles?
504:      * @param boolean $dironly    Show only directories?
505:      * @param boolean $recursive  Return all directory levels recursively?
506:      *
507:      * @return array  File list.
508:      * @throws Horde_Vfs_Exception
509:      */
510:     public function listFolder($path, $filter = null, $dotfiles = true,
511:                                $dironly = false, $recursive = false)
512:     {
513:         $list = $this->_listFolder($path, $filter, $dotfiles, $dironly);
514:         if (!$recursive) {
515:             return $list;
516:         }
517: 
518:         if (strlen($path)) {
519:             $path .= '/';
520:         }
521:         foreach ($list as $name => $values) {
522:             if ($values['type'] == '**dir') {
523:                 $list[$name]['subdirs'] = $this->listFolder($path . $name, $filter, $dotfiles, $dironly, $recursive);
524:             }
525:         }
526: 
527:         return $list;
528:     }
529: 
530:     /**
531:      * Returns an an unsorted file list of the specified directory.
532:      *
533:      * @abstract
534:      *
535:      * @param string $path       The path of the directory.
536:      * @param mixed $filter      String/hash to filter file/dirname on.
537:      * @param boolean $dotfiles  Show dotfiles?
538:      * @param boolean $dironly   Show only directories?
539:      *
540:      * @return array  File list.
541:      * @throws Horde_Vfs_Exception
542:      */
543:     protected function _listFolder($path, $filter = null, $dotfiles = true,
544:                                    $dironly = false)
545:     {
546:         throw new Horde_Vfs_Exception('Not supported.');
547:     }
548: 
549:     /**
550:      * Returns the current working directory of the VFS backend.
551:      *
552:      * @return string  The current working directory.
553:      */
554:     public function getCurrentDirectory()
555:     {
556:         return '';
557:     }
558: 
559:     /**
560:      * Returns whether or not a filename matches any filter element.
561:      *
562:      * @param mixed $filter     String/hash to build the regular expression
563:      *                          from.
564:      * @param string $filename  String containing the filename to match.
565:      *
566:      * @return boolean  True on match, false on no match.
567:      */
568:     protected function _filterMatch($filter, $filename)
569:     {
570:         $namefilter = null;
571: 
572:         // Build a regexp based on $filter.
573:         if (!is_null($filter)) {
574:             $namefilter = '/';
575:             if (is_array($filter)) {
576:                 $once = false;
577:                 foreach ($filter as $item) {
578:                     if ($once !== true) {
579:                         $once = true;
580:                     } else {
581:                         $namefilter .= '|';
582:                     }
583:                     $namefilter .= '(' . $item . ')';
584:                 }
585:             } else {
586:                 $namefilter .= '(' . $filter . ')';
587:             }
588:             $namefilter .= '/';
589:         }
590: 
591:         $match = false;
592:         if (!is_null($namefilter)) {
593:             $match = preg_match($namefilter, $filename);
594:         }
595: 
596:         return $match;
597:     }
598: 
599:     /**
600:      * Changes permissions for an item on the VFS.
601:      *
602:      * @abstract
603:      *
604:      * @param string $path        The parent folder of the item.
605:      * @param string $name        The name of the item.
606:      * @param string $permission  The permission to set.
607:      *
608:      * @throws Horde_Vfs_Exception
609:      */
610:     public function changePermissions($path, $name, $permission)
611:     {
612:         throw new Horde_Vfs_Exception('Not supported.');
613:     }
614: 
615:     /**
616:      * Returns a sorted list of folders in the specified directory.
617:      *
618:      * @abstract
619:      *
620:      * @param string $path         The path of the directory to get the
621:      *                             directory list for.
622:      * @param mixed $filter        Hash of items to filter based on folderlist.
623:      * @param boolean $dotfolders  Include dotfolders?
624:      *
625:      * @return array  Folder list.
626:      * @throws Horde_Vfs_Exception
627:      */
628:     public function listFolders($path = '', $filter = null, $dotfolders = true)
629:     {
630:         throw new Horde_Vfs_Exception('Not supported.');
631:     }
632: 
633:     /**
634:      * Returns the list of additional credentials required, if any.
635:      *
636:      * @return array  Credential list.
637:      */
638:     public function getRequiredCredentials()
639:     {
640:         return array_diff($this->_credentials, array_keys($this->_params));
641:     }
642: 
643:     /**
644:      * Returns an array specifying what permissions are changeable for this
645:      * VFS implementation.
646:      *
647:      * @return array  Changeable permisions.
648:      */
649:     public function getModifiablePermissions()
650:     {
651:         return $this->_permissions;
652:     }
653: 
654:     /**
655:      * Returns the size of the VFS item.
656:      *
657:      * @return integer  The size, in bytes, of the VFS item.
658:      */
659:     public function getVFSSize()
660:     {
661:         if (is_null($this->_vfsSize)) {
662:             $this->_vfsSize = $this->getFolderSize($this->_params['vfs_quotaroot']);
663:         }
664:         return $this->_vfsSize;
665:     }
666: 
667:     /**
668:      * Sets the VFS quota limit.
669:      *
670:      * @param integer $quota   The limit to apply.
671:      * @param integer $metric  The metric to multiply the quota into.
672:      */
673:     public function setQuota($quota, $metric = Horde_Vfs::QUOTA_METRIC_BYTE)
674:     {
675:         switch ($metric) {
676:         case Horde_Vfs::QUOTA_METRIC_KB:
677:             $quota *= pow(2, 10);
678:             break;
679: 
680:         case Horde_Vfs::QUOTA_METRIC_MB:
681:             $quota *= pow(2, 20);
682:             break;
683: 
684:         case Horde_Vfs::QUOTA_METRIC_GB:
685:             $quota *= pow(2, 30);
686:             break;
687:         }
688: 
689:         $this->_params['vfs_quotalimit'] = $quota;
690:     }
691: 
692:     /**
693:      * Sets the VFS quota root.
694:      *
695:      * @param string $dir  The root directory for the quota determination.
696:      */
697:     public function setQuotaRoot($dir)
698:     {
699:         $this->_params['vfs_quotaroot'] = $dir;
700:     }
701: 
702:     /**
703:      * Get quota information (used/allocated), in bytes.
704:      *
705:      * @return mixed  An associative array.
706:      * <pre>
707:      * 'limit' = Maximum quota allowed
708:      * 'usage' = Currently used portion of quota (in bytes)
709:      * </pre>
710:      * @throws Horde_Vfs_Exception
711:      */
712:     public function getQuota()
713:     {
714:         if ($this->_params['vfs_quotalimit'] == -1) {
715:             throw new Horde_Vfs_Exception('No quota set.');
716:         }
717: 
718:         return array(
719:             'limit' => $this->_params['vfs_quotalimit'],
720:             'usage' => $this->getVFSSize()
721:         );
722:     }
723: 
724:     /**
725:      * Checks the quota when preparing to write data.
726:      *
727:      * @param string $mode   Either 'string' or 'file'.  If 'string', $data is
728:      *                       the data to be written.  If 'file', $data is the
729:      *                       filename containing the data to be written.
730:      * @param string $data   Either the data or the filename to the data.
731:      *
732:      * @throws Horde_Vfs_Exception
733:      */
734:     protected function _checkQuotaWrite($mode, $data)
735:     {
736:         if ($this->_params['vfs_quotalimit'] == -1 &&
737:             is_null($this->_vfsSize)) {
738:             return;
739:         }
740: 
741:         if ($mode == 'file') {
742:             $filesize = filesize($data);
743:             if ($filesize === false) {
744:                 throw new Horde_Vfs_Exception('Unable to read VFS file (filesize() failed).');
745:             }
746:         } else {
747:             $filesize = strlen($data);
748:         }
749: 
750:         $vfssize = $this->getVFSSize();
751:         if ($this->_params['vfs_quotalimit'] > -1 &&
752:             ($vfssize + $filesize) > $this->_params['vfs_quotalimit']) {
753:             throw new Horde_Vfs_Exception('Unable to write VFS file, quota will be exceeded.');
754:         }
755: 
756:         if (!is_null($this->_vfsSize)) {
757:             $this->_vfsSize += $filesize;
758:         }
759:     }
760: 
761:     /**
762:      * Checks the quota when preparing to delete data.
763:      *
764:      * @param string $path  The path the file is located in.
765:      * @param string $name  The filename.
766:      *
767:      * @throws Horde_Vfs_Exception
768:      */
769:     protected function _checkQuotaDelete($path, $name)
770:     {
771:         if (!is_null($this->_vfsSize)) {
772:             $this->_vfsSize -= $this->size($path, $name);
773:         }
774:     }
775: 
776:     /**
777:      * Returns the full path of an item.
778:      *
779:      * @param string $path  The path of directory of the item.
780:      * @param string $name  The name of the item.
781:      *
782:      * @return mixed  Full path when $path isset and just $name when not set.
783:      */
784:     protected function _getPath($path, $name)
785:     {
786:         if (strlen($path) > 0) {
787:             if (substr($path, -1) == '/') {
788:                 return $path . $name;
789:             }
790:             return $path . '/' . $name;
791:         }
792: 
793:         return $name;
794:     }
795: }
796: 
API documentation generated by ApiGen