VFS
[ class tree: VFS ] [ index: VFS ] [ all elements ]

Source for file musql.php

Documentation is available at musql.php

  1. <?php
  2.  
  3. require_once dirname(__FILE__'/sql.php';
  4.  
  5. /**
  6.  * Permission for read access.
  7.  */
  8. define('VFS_FLAG_READ'1);
  9.  
  10. /**
  11.  * Permission for read access.
  12.  */
  13. define('VFS_FLAG_WRITE'2);
  14.  
  15. /**
  16.  * Multi User VFS implementation for PHP's PEAR database
  17.  * abstraction layer.
  18.  *
  19.  * Required values for $params:<pre>
  20.  *      'phptype'       The database type (ie. 'pgsql', 'mysql', etc.).</pre>
  21.  *
  22.  * Optional values:<pre>
  23.  *      'table'         The name of the vfs table in 'database'. Defaults to
  24.  *                      'horde_muvfs'.</pre>
  25.  *
  26.  * Required by some database implementations:<pre>
  27.  *      'hostspec'      The hostname of the database server.
  28.  *      'protocol'      The communication protocol ('tcp', 'unix', etc.).
  29.  *      'database'      The name of the database.
  30.  *      'username'      The username with which to connect to the database.
  31.  *      'password'      The password associated with 'username'.
  32.  *      'options'       Additional options to pass to the database.
  33.  *      'tty'           The TTY on which to connect to the database.
  34.  *      'port'          The port on which to connect to the database.</pre>
  35.  *
  36.  * Known Issues:
  37.  * Delete is not recusive, so files and folders that used to be in a folder
  38.  * that gets deleted live forever in the database, or re-appear when the folder
  39.  * is recreated.
  40.  * Rename has the same issue, so files are lost if a folder is renamed.
  41.  *
  42.  * The table structure for the VFS can be found in
  43.  * data/muvfs.sql.
  44.  *
  45.  * Database specific notes:
  46.  *
  47.  * MSSQL:
  48.  * - The vfs_data field must be of type IMAGE.
  49.  * - You need the following php.ini settings:
  50.  * <code>
  51.  *    ; Valid range 0 - 2147483647. Default = 4096.
  52.  *    mssql.textlimit = 0 ; zero to pass through
  53.  *
  54.  *    ; Valid range 0 - 2147483647. Default = 4096.
  55.  *    mssql.textsize = 0 ; zero to pass through
  56.  * </code>
  57.  *
  58.  * $Horde: framework/VFS/lib/VFS/musql.php,v 1.1.2.4 2009/01/06 15:23:47 jan Exp $
  59.  *
  60.  * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
  61.  *
  62.  * See the enclosed file COPYING for license information (LGPL). If you
  63.  * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  64.  *
  65.  * @author  Chuck Hagenbuch <chuck@horde.org>
  66.  * @author  Mike Cochrane <mike@graftonhall.co.nz>
  67.  * @package VFS
  68.  */
  69. class VFS_musql extends VFS_sql {
  70.  
  71.     /**
  72.      * List of permissions and if they can be changed in this VFS
  73.      *
  74.      * @var array 
  75.      */
  76.     var $_permissions = array(
  77.         'owner' => array('read' => false'write' => false'execute' => false),
  78.         'group' => array('read' => false'write' => false'execute' => false),
  79.         'all'   => array('read' => true,  'write' => true,  'execute' => false)
  80.     );
  81.  
  82.     /**
  83.      * Stores a file in the VFS from raw data.
  84.      *
  85.      * @param string $path         The path to store the file in.
  86.      * @param string $name         The filename to use.
  87.      * @param string $data         The file data.
  88.      * @param boolean $autocreate  Automatically create directories?
  89.      *
  90.      * @return mixed  True on success or a PEAR_Error object on failure.
  91.      */
  92.     function writeData($path$name$data$autocreate = false)
  93.     {
  94.         $conn $this->_connect();
  95.         if (PEAR::isError($conn)) {
  96.             return $conn;
  97.         }
  98.  
  99.         /* Make sure we have write access to this and all parent paths. */
  100.         if ($path != ''{
  101.             $paths explode('/'$path);
  102.             $path_name array_pop($paths);
  103.             if (!$this->isFolder(implode('/'$paths)$path_name)) {
  104.                 if (!$autocreate{
  105.                     return PEAR::raiseError(
  106.                         sprintf(_("Folder \"%s\" does not exist")$path),
  107.                         'horde.error');
  108.                 else {
  109.                     $result $this->autocreatePath($path);
  110.                     if (is_a($result'PEAR_Error')) {
  111.                         return $result;
  112.                     }
  113.                 }
  114.             }
  115.             $paths[$path_name;
  116.             $previous '';
  117.  
  118.             foreach ($paths as $thispath{
  119.                 $sql sprintf('SELECT vfs_owner, vfs_perms FROM %s
  120.                                 WHERE vfs_path = ? AND vfs_name= ?',
  121.                                $this->_params['table']);
  122.                 $this->log($sqlPEAR_LOG_DEBUG);
  123.                 $results $this->_db->getAll($sqlarray($previous$thispath));
  124.                 if (is_a($results'PEAR_Error')) {
  125.                     $this->log($resultsPEAR_LOG_ERR);
  126.                     return $results;
  127.                 }
  128.                 if (!is_array($results|| count($results< 1{
  129.                     return PEAR::raiseError(_("Unable to create VFS file."));
  130.                 }
  131.  
  132.                 $allowed = false;
  133.                 foreach ($results as $result{
  134.                     if ($result[0== $this->_params['user'||
  135.                         $result[1VFS_FLAG_WRITE{
  136.                         $allowed = true;
  137.                         break;
  138.                     }
  139.                 }
  140.  
  141.                 if (!$allowed{
  142.                     return PEAR::raiseError(_("Access denied creating VFS file."));
  143.                 }
  144.  
  145.                 $previous $thispath;
  146.             }
  147.         }
  148.  
  149.         return parent::writeData($path$name$data$autocreate);
  150.     }
  151.  
  152.     /**
  153.      * Deletes a file from the VFS.
  154.      *
  155.      * @param string $path  The path to store the file in.
  156.      * @param string $name  The filename to use.
  157.      *
  158.      * @return mixed  True on success or a PEAR_Error object on failure.
  159.      */
  160.     function deleteFile($path$name)
  161.     {
  162.         $conn $this->_connect();
  163.         if (PEAR::isError($conn)) {
  164.             return $conn;
  165.         }
  166.  
  167.         $sql sprintf('SELECT vfs_id, vfs_owner, vfs_perms FROM %s
  168.                         WHERE vfs_path = ? AND vfs_name= ? AND vfs_type = ?',
  169.                        $this->_params['table']);
  170.         $this->log($sqlPEAR_LOG_DEBUG);
  171.         $fileList $this->_db->getAll($sqlarray($path$nameVFS_FILE));
  172.  
  173.         if (is_a($fileList'PEAR_Error')) {
  174.             $this->log($fileListPEAR_LOG_ERR);
  175.             return $fileList;
  176.         }
  177.         if (!is_array($fileList|| count($fileList< 1{
  178.             return PEAR::raiseError(_("Unable to delete VFS file."));
  179.         }
  180.  
  181.         /* There may be one or more files with the same name but the user may
  182.          * not have read access to them, so doesn't see them. So we have to
  183.          * delete the one they have access to. */
  184.         foreach ($fileList as $file{
  185.             if ($file[1== $this->_params['user'||
  186.                 $file[2VFS_FLAG_WRITE{
  187.                 $sql sprintf('DELETE FROM %s WHERE vfs_id = ?',
  188.                                $this->_params['table']);
  189.                 $this->log($sqlPEAR_LOG_DEBUG);
  190.                 $result $this->_db->query($sqlarray($file[0]));
  191.  
  192.                 if (is_a($result'PEAR_Error')) {
  193.                     $this->log($resultPEAR_LOG_ERR);
  194.                     return $result;
  195.                 }
  196.                 if ($this->_db->affectedRows(== 0{
  197.                     return PEAR::raiseError(_("Unable to delete VFS file."));
  198.                 }
  199.                 return $result;
  200.             }
  201.         }
  202.  
  203.         // FIXME: 'Access Denied deleting file %s/%s'
  204.         return PEAR::raiseError(_("Unable to delete VFS file."));
  205.     }
  206.  
  207.     /**
  208.      * Renames a file or folder in the VFS.
  209.      *
  210.      * @param string $oldpath  The old path to the file.
  211.      * @param string $oldname  The old filename.
  212.      * @param string $newpath  The new path of the file.
  213.      * @param string $newname  The new filename.
  214.      *
  215.      * @return mixed  True on success or a PEAR_Error object on failure.
  216.      */
  217.     function rename($oldpath$oldname$newpath$newname)
  218.     {
  219.         $conn $this->_connect();
  220.         if (PEAR::isError($conn)) {
  221.             return $conn;
  222.         }
  223.  
  224.         $sql sprintf('SELECT vfs_id, vfs_owner, vfs_perms FROM %s
  225.                         WHERE vfs_path = ? AND vfs_name= ?',
  226.                        $this->_params['table']);
  227.         $this->log($sqlPEAR_LOG_DEBUG);
  228.         $fileList $this->_db->getAll($sqlarray($oldpath$oldname));
  229.  
  230.         if (is_a($fileList'PEAR_Error')) {
  231.             $this->log($fileListPEAR_LOG_ERR);
  232.             return $fileList;
  233.         }
  234.         if (!is_array($fileList|| count($fileList< 1{
  235.             return PEAR::raiseError(_("Unable to rename VFS file."));
  236.         }
  237.  
  238.         if (strpos($newpath'/'=== false{
  239.             $parent '';
  240.             $path $newpath;
  241.         else {
  242.             list($parent$pathexplode('/'$newpath2);
  243.         }
  244.         if (!$this->isFolder($parent$path)) {
  245.             if (is_a($result $this->autocreatePath($newpath)'PEAR_Error')) {
  246.                 return $result;
  247.             }
  248.         }
  249.  
  250.         /* There may be one or more files with the same name but the user may
  251.          * not have read access to them, so doesn't see them. So we have to
  252.          * rename the one they have access to. */
  253.         foreach ($fileList as $file{
  254.             if ($file[1== $this->_params['user'||
  255.                 $file[2VFS_FLAG_WRITE{
  256.                 $sql sprintf('UPDATE %s SET vfs_path = ?, vfs_name = ?, vfs_modified = ?
  257.                                 WHERE vfs_id = ?',
  258.                                $this->_params['table']);
  259.                 $this->log($sqlPEAR_LOG_DEBUG);
  260.                 $result $this->_db->query(
  261.                     $sql,
  262.                     array($newpath$newnametime()$file[0]));
  263.                 if (is_a($result'PEAR_Error')) {
  264.                     $this->log($resultPEAR_LOG_ERR);
  265.                     return $result;
  266.                 }
  267.                 return $result;
  268.             }
  269.         }
  270.  
  271.         return PEAR::raiseError(sprintf(_("Unable to rename VFS file %s/%s."),
  272.                                         $oldpath$oldname));
  273.     }
  274.  
  275.     /**
  276.      * Creates a folder on the VFS.
  277.      *
  278.      * @param string $path  Holds the path of directory to create folder.
  279.      * @param string $name  Holds the name of the new folder.
  280.      *
  281.      * @return mixed  True on success or a PEAR_Error object on failure.
  282.      */
  283.     function createFolder($path$name)
  284.     {
  285.         $conn $this->_connect();
  286.         if (PEAR::isError($conn)) {
  287.             return $conn;
  288.         }
  289.  
  290.         /* Make sure we have write access to this and all parent paths. */
  291.         if (strlen($path)) {
  292.             $paths explode('/'$path);
  293.             $previous '';
  294.  
  295.             foreach ($paths as $thispath{
  296.                 $sql sprintf('SELECT vfs_owner, vfs_perms FROM %s
  297.                                 WHERE vfs_path = ? AND vfs_name= ?',
  298.                                $this->_params['table']);
  299.                 $this->log($sqlPEAR_LOG_DEBUG);
  300.                 $results $this->_db->getAll($sqlarray($previous$thispath));
  301.                 if (is_a($results'PEAR_Error')) {
  302.                     $this->log($resultsPEAR_LOG_ERR);
  303.                     return $results;
  304.                 }
  305.                 if (!is_array($results|| count($results< 1{
  306.                     return PEAR::raiseError(_("Unable to create VFS directory."));
  307.                 }
  308.  
  309.                 $allowed = false;
  310.                 foreach ($results as $result{
  311.                     if ($result[0== $this->_params['user'||
  312.                         $result[1VFS_FLAG_WRITE{
  313.                         $allowed = true;
  314.                         break;
  315.                     }
  316.                 }
  317.  
  318.                 if (!$allowed{
  319.                     return PEAR::raiseError(_("Access denied creating VFS directory."));
  320.                 }
  321.  
  322.                 $previous $thispath;
  323.             }
  324.         }
  325.  
  326.         $id $this->_db->nextId($this->_params['table']);
  327.         $sql sprintf('INSERT INTO %s
  328.                         (vfs_id, vfs_type, vfs_path, vfs_name, vfs_modified, vfs_owner, vfs_perms)
  329.                         VALUES (?, ?, ?, ?, ?, ?, ?)',
  330.                        $this->_params['table']);
  331.         $this->log($sqlPEAR_LOG_DEBUG);
  332.         $result $this->_db->query(
  333.             $sql,
  334.             array($idVFS_FOLDER$path$nametime()$this->_params['user']0));
  335.         var_dump($this->_db->last_query);
  336.         if (is_a($result'PEAR_Error')) {
  337.             $this->log($resultPEAR_LOG_ERR);
  338.         }
  339.  
  340.         return $result;
  341.     }
  342.  
  343.     /**
  344.      * Deletes a folder from the VFS.
  345.      *
  346.      * @param string $path        The path to delete the folder from.
  347.      * @param string $name        The foldername to use.
  348.      * @param boolean $recursive  Force a recursive delete?
  349.      *
  350.      * @return mixed  True on success or a PEAR_Error object on failure.
  351.      */
  352.     function deleteFolder($path$name$recursive = false)
  353.     {
  354.         $conn $this->_connect();
  355.         if (PEAR::isError($conn)) {
  356.             return $conn;
  357.         }
  358.  
  359.         if ($recursive{
  360.             $result $this->emptyFolder($path '/' $name);
  361.             if (is_a($result'PEAR_Error')) {
  362.                 return $result;
  363.             }
  364.         else {
  365.             $list $this->listFolder($path '/' $name);
  366.             if (is_a($list'PEAR_Error')) {
  367.                 return $list;
  368.             }
  369.             if (count($list)) {
  370.                 return PEAR::raiseError(
  371.                     sprintf(_("Unable to delete %s, the directory is not empty"),
  372.                             $path '/' $name));
  373.             }
  374.         }
  375.  
  376.         $sql sprintf('SELECT vfs_id, vfs_owner, vfs_perms FROM %s
  377.                         WHERE vfs_path = ? AND vfs_name= ? AND vfs_type = ?',
  378.                        $this->_params['table']);
  379.         $this->log($sqlPEAR_LOG_DEBUG);
  380.         $fileList $this->_db->getAll($sqlarray($path$nameVFS_FOLDER));
  381.  
  382.         if (is_a($fileList'PEAR_Error')) {
  383.             $this->log($fileListPEAR_LOG_ERR);
  384.             return $fileList;
  385.         }
  386.         if (!is_array($fileList|| count($fileList< 1{
  387.             return PEAR::raiseError(_("Unable to delete VFS directory."));
  388.         }
  389.  
  390.         /* There may be one or more folders with the same name but as the user
  391.          * may not have read access to them, they don't see them. So we have
  392.          * to delete the one they have access to */
  393.         foreach ($fileList as $file{
  394.             if ($file[1== $this->_params['user'||
  395.                 $file[2VFS_FLAG_WRITE{
  396.                 $sql sprintf('DELETE FROM %s WHERE vfs_id = ?',
  397.                                $this->_params['table']);
  398.                 $this->log($sqlPEAR_LOG_DEBUG);
  399.                 $result $this->_db->query($sqlarray($file[0]));
  400.  
  401.                 if (is_a($result'PEAR_Error')) {
  402.                     $this->log($resultPEAR_LOG_ERR);
  403.                     return $result;
  404.                 }
  405.                 if ($this->_db->affectedRows(== 0{
  406.                     return PEAR::raiseError(_("Unable to delete VFS directory."));
  407.                 }
  408.  
  409.                 return $result;
  410.             }
  411.         }
  412.  
  413.         // FIXME: 'Access Denied deleting folder %s/%s'
  414.         return PEAR::raiseError(_("Unable to delete VFS directory."));
  415.     }
  416.  
  417.     /**
  418.      * Returns a list of the contents of a folder.
  419.      *
  420.      * @param string $path       The path of the directory.
  421.      * @param mixed $filter      String/hash to filter file/dirname on.
  422.      * @param boolean $dotfiles  Show dotfiles?
  423.      * @param boolean $dironly   Show only directories?
  424.      *
  425.      * @return mixed  File list on success or false on failure.
  426.      */
  427.     function _listFolder($path$filter = null$dotfiles = true,
  428.                         $dironly = false)
  429.     {
  430.         $conn $this->_connect();
  431.         if (is_a($conn'PEAR_Error')) {
  432.             return $conn;
  433.         }
  434.  
  435.         $length_op $this->_getFileSizeOp();
  436.         $sql sprintf('SELECT vfs_name, vfs_type, vfs_modified, vfs_owner, vfs_perms, %s(vfs_data) FROM %s
  437.                         WHERE vfs_path = ? AND (vfs_owner = ? OR vfs_perms \&\& ?)',
  438.                        $length_op$this->_params['table']);
  439.         $this->log($sqlPEAR_LOG_DEBUG);
  440.         $fileList $this->_db->getAll(
  441.             $sql,
  442.             array($path$this->_params['user']VFS_FLAG_READ));
  443.         if (is_a($fileList'PEAR_Error')) {
  444.             $this->log($fileListPEAR_LOG_ERR);
  445.             return $fileList;
  446.         }
  447.  
  448.         $files = array();
  449.         foreach ($fileList as $line{
  450.             // Filter out dotfiles if they aren't wanted.
  451.             if (!$dotfiles && substr($line[0]01== '.'{
  452.                 continue;
  453.             }
  454.  
  455.             $file['name'stripslashes($line[0]);
  456.  
  457.             if ($line[1== VFS_FILE{
  458.                 $name explode('.'$line[0]);
  459.  
  460.                 if (count($name== 1{
  461.                     $file['type''**none';
  462.                 else {
  463.                     $file['type'VFS::strtolower($name[count($name- 1]);
  464.                 }
  465.  
  466.                 $file['size'$line[5];
  467.             elseif ($line[1== VFS_FOLDER{
  468.                 $file['type''**dir';
  469.                 $file['size'= -1;
  470.             }
  471.  
  472.             $file['date'$line[2];
  473.             $file['owner'$line[3];
  474.  
  475.             $line[4intval($line[4]);
  476.             $file['perms']  ($line[1== VFS_FOLDER'd' '-';
  477.             $file['perms'.= 'rw-';
  478.             $file['perms'.= ($line[4VFS_FLAG_READ'r' '-';
  479.             $file['perms'.= ($line[4VFS_FLAG_WRITE'w' '-';
  480.             $file['perms'.= '-';
  481.             $file['group''';
  482.  
  483.             // Filtering.
  484.             if ($this->_filterMatch($filter$file['name'])) {
  485.                 unset($file);
  486.                 continue;
  487.             }
  488.             if ($dironly && $file['type'!== '**dir'{
  489.                 unset($file);
  490.                 continue;
  491.             }
  492.  
  493.             $files[$file['name']] $file;
  494.             unset($file);
  495.         }
  496.  
  497.         return $files;
  498.     }
  499.  
  500.     /**
  501.      * Changes permissions for an Item on the VFS.
  502.      *
  503.      * @param string $path  Holds the path of directory of the Item.
  504.      * @param string $name  Holds the name of the Item.
  505.      *
  506.      * @return mixed  True on success or a PEAR_Error object on failure.
  507.      */
  508.     function changePermissions($path$name$permission)
  509.     {
  510.         $conn $this->_connect();
  511.         if (PEAR::isError($conn)) {
  512.             return $conn;
  513.         }
  514.  
  515.         $val intval(substr($permission-1));
  516.         $perm = 0;
  517.         $perm |= ($val 4VFS_FLAG_READ : 0;
  518.         $perm |= ($val 2VFS_FLAG_WRITE : 0;
  519.  
  520.         $sql sprintf('SELECT vfs_id, vfs_owner, vfs_perms FROM %s
  521.                         WHERE vfs_path = ? AND vfs_name= ?',
  522.                        $this->_params['table']);
  523.         $this->log($sqlPEAR_LOG_DEBUG);
  524.         $fileList $this->_db->getAll($sqlarray($path$name));
  525.  
  526.         if (is_a($fileList'PEAR_Error')) {
  527.             $this->log($fileListPEAR_LOG_ERR);
  528.             return $fileList;
  529.         }
  530.         if (!is_array($fileList|| count($fileList< 1{
  531.             return PEAR::raiseError(_("Unable to rename VFS file."));
  532.         }
  533.  
  534.         /* There may be one or more files with the same name but the user may
  535.          * not have read access to them, so doesn't see them. So we have to
  536.          * chmod the one they have access to. */
  537.         foreach ($fileList as $file{
  538.             if ($file[1== $this->_params['user'||
  539.                 $file[2VFS_FLAG_WRITE{
  540.                 $sql sprintf('UPDATE %s SET vfs_perms = ?
  541.                                 WHERE vfs_id = ?',
  542.                                $this->_params['table']);
  543.                 $this->log($sqlPEAR_LOG_DEBUG);
  544.                 $result $this->_db->query($sqlarray($perm$file[0]));
  545.                 return $result;
  546.             }
  547.         }
  548.  
  549.         return PEAR::raiseError(
  550.             sprintf(_("Unable to change permission for VFS file %s/%s."),
  551.                     $path$name));
  552.     }
  553.  
  554. }

Documentation generated on Mon, 11 Mar 2019 15:34:54 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.