diff --git a/phpgwapi/inc/class.vfs_sql.inc.php b/phpgwapi/inc/class.vfs_sql.inc.php
index 8329b6b1f5..2a601f8219 100644
--- a/phpgwapi/inc/class.vfs_sql.inc.php
+++ b/phpgwapi/inc/class.vfs_sql.inc.php
@@ -43,7 +43,7 @@
/* These are used in calls to extra_sql () */
define ('VFS_SQL_SELECT', 1);
define ('VFS_SQL_DELETE', 2);
- define ('VFS_SQL_UPDATE', 2);
+ define ('VFS_SQL_UPDATE', 4);
/* These are used in calls to add_journal (), and allow journal messages to be more standard */
define ('VFS_OPERATION_CREATED', 1);
@@ -81,855 +81,471 @@
}
-class vfs
-{
- var $basedir;
- var $fakebase;
- var $relative;
- var $working_id;
- var $working_lid;
- var $attributes;
- var $override_acl;
- var $linked_dirs;
- var $meta_types;
-
- /*!
- @function vfs
- @abstract constructor, sets up variables
- */
-
- function vfs ()
+ class vfs
{
- global $phpgw, $phpgw_info;
-
- $this->basedir = $phpgw_info["server"]["files_dir"];
- $this->fakebase = "/home";
- $this->working_id = $phpgw_info["user"]["account_id"];
- $this->working_lid = $phpgw->accounts->id2name ($this->working_id);
- $this->now = date ("Y-m-d");
- $this->override_acl = 0;
-
- /*
- File/dir attributes, each corresponding to a database field. Useful for use in loops
- If an attribute was added to the table, add it here and possibly add it to
- set_attributes ()
- */
-
- $this->attributes = array ("file_id", "owner_id", "createdby_id", "modifiedby_id", "created", "modified", "size", "mime_type", "deleteable", "comment", "app", "directory", "name", "link_directory", "link_name", "version");
-
- /*
- These are stored in the MIME-type field and should normally be ignored.
- Adding a type here will ensure it is normally ignored, but you will have to
- explicitly add it to acl_check (), and to any other SELECT's in this file
- */
-
- $this->meta_types = array ("journal", "journal-deleted");
-
- /* We store the linked directories in an array now, so we don't have to make the SQL call again */
-
- $query = $phpgw->db->query ("SELECT directory, name, link_directory, link_name FROM phpgw_vfs WHERE link_directory != '' AND link_name != ''" . $this->extra_sql (VFS_SQL_SELECT));
-
- $this->linked_dirs = array ();
- while ($phpgw->db->next_record ())
- {
- $this->linked_dirs[] = $phpgw->db->Record;
- }
- }
-
- /*!
- @function set_relative
- @abstract Set path relativity
- @param $mask Relative bitmask (see RELATIVE_ defines)
- */
-
- function set_relative ($mask)
- {
- if (!$mask)
- unset ($this->relative);
- else
- $this->relative = $mask;
- }
-
- /*!
- @function get_relative
- @abstract Return relativity bitmask
- @discussion Returns relativity bitmask, or the default of "completely relative" if unset
- */
-
- function get_relative ()
- {
- if (isset ($this->relative))
- return $this->relative;
- else
- return RELATIVE_ALL;
- }
-
- /*!
- @function sanitize
- @abstract Removes leading .'s from $string
- @discussion You should not pass all filenames through sanitize () unless you plan on rejecting
- .files. Instead, pass the name through securitycheck () first, and if it fails,
- pass it through sanitize
- @param $string string to sanitize
- @result $string without it's leading .'s
- */
-
- function sanitize ($string)
- {
- global $phpgw, $phpgw_info;
-
- /* We use path_parts () just to parse the string, not translate paths */
- $p = $this->path_parts ($string, array (RELATIVE_NONE));
-
- return (ereg_replace ("^\.+", "", $p->fake_name));
- }
-
- /*!
- @function securitycheck
- @abstract Security check function
- @discussion Checks for basic violations such as ..
- If securitycheck () fails, run your string through vfs->sanitize ()
- @param $string string to check security of
- @result Boolean True/False. True means secure, False means insecure
- */
-
- function securitycheck ($string)
- {
- if (substr ($string, 0, 1) == "\\" || strstr ($string, "..") || strstr ($string, "\\..") || strstr ($string, ".\\."))
- {
- return False;
- }
- else
- {
- return True;
- }
- }
-
- /*!
- @function db_clean
- @abstract Clean $string for use in database queries
- @param $string String to clean
- @result Cleaned version of $string
- */
-
- function db_clean ($string)
- {
- $string = ereg_replace ("'", "\'", $string);
-
- return $string;
- }
-
- /*!
- @function extra_sql
- @abstract Return extra SQL code that should be appended to certain queries
- @param $query_type The type of query to get extra SQL code for, in the form of a VFS_SQL define
- @result Extra SQL code
- */
-
- function extra_sql ($query_type = VFS_SQL_SELECT)
- {
- global $phpgw, $phpgw_info;
-
- if ($query_type == VFS_SQL_SELECT || $query_type == VFS_SQL_DELETE || $query_type = VFS_SQL_UPDATE)
- {
- $sql = " AND ((";
-
- reset ($this->meta_types);
- while (list ($num, $type) = each ($this->meta_types))
- {
- if ($num)
- $sql .= " AND ";
-
- $sql .= "mime_type != '$type'";
- }
-
- $sql .= ") OR mime_type IS NULL)";
- }
-
- return ($sql);
- }
-
- /*!
- @function add_journal
- @abstract Add a journal entry after (or before) completing an operation,
- and increment the version number. This function should be used internally only
- @discussion Note that $state_one and $state_two are ignored for some VFS_OPERATION's, for others
- they are required. They are ignored for any "custom" operation
- The two operations that require $state_two:
- $operation $state_two
- VFS_OPERATION_COPIED fake_full_path of copied to
- VFS_OPERATION_MOVED fake_full_path of moved to
-
- If deleting, you must call add_journal () before you delete the entry from the database
- @param $string File or directory to add entry for
- @param $relatives Relativity array
- @param $operation The operation that was performed. Either a VFS_OPERATION define or
- a non-integer descriptive text string
- @param $state_one The first "state" of the file or directory. Can be a file name, size,
- location, whatever is appropriate for the specific operation
- @param $state_two The second "state" of the file or directory
- @param $incversion Boolean True/False. Increment the version for the file? Note that this is
- handled automatically for the VFS_OPERATION defines.
- i.e. VFS_OPERATION_EDITED would increment the version, VFS_OPERATION_COPIED
- would not
- @result Boolean True/False
- */
-
- function add_journal ($string, $relatives = array (RELATIVE_CURRENT), $operation, $state_one, $state_two, $incversion = True)
- {
- global $phpgw, $phpgw_info;
-
- $account_id = $phpgw_info["user"]["account_id"];
-
- $p = $this->path_parts ($string, array ($relatives[0]));
-
- /* We check that they have some sort of access to the file other than read */
- if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_WRITE) && !$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_EDIT) && !$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_DELETE))
- {
- return False;
- }
-
- if (!$this->file_exists ($p->fake_full_path, array ($p->mask)))
- {
- return False;
- }
-
- $ls_array = $this->ls ($p->fake_full_path, array ($p->mask), False, False, True);
- $file_array = $ls_array[0];
-
- $sql = "INSERT INTO phpgw_vfs (";
- $sql2 .= " VALUES (";
-
- for ($i = 0; list ($attribute, $value) = each ($file_array); $i++)
- {
- if ($attribute == "file_id")
- {
- continue;
- }
-
- if ($i > 1)
- {
- $sql .= ", ";
- $sql2 .= ", ";
- }
-
- if ($attribute == "owner_id")
- {
- $value = $account_id;
- }
-
- if ($attribute == "created")
- {
- $value = $this->now;
- }
-
- if ($attribute == "mime_type")
- {
- $value = "journal";
- }
-
- if ($attribute == "comment")
- {
- switch ($operation)
- {
- case VFS_OPERATION_CREATED:
- $value = "Created";
- $incversion = True;
- break;
- case VFS_OPERATION_EDITED:
- $value = "Edited";
- $incversion = True;
- break;
- case VFS_OPERATION_EDITED_COMMENT:
- $value = "Edited comment";
- $incversion = False;
- break;
- case VFS_OPERATION_COPIED:
- if (!$state_one)
- $state_one = $p->fake_full_path;
- if (!$state_two)
- return False;
- $value = "Copied $state_one to $state_two";
- $incversion = False;
- break;
- case VFS_OPERATION_MOVED:
- if (!$state_one)
- $state_one = $p->fake_full_path;
- if (!$state_two)
- return False;
- $value = "Moved $state_one to $state_two";
- $incversion = False;
- break;
- case VFS_OPERATION_DELETED:
- $value = "Deleted";
- $incversion = False;
- break;
- default:
- $value = $operation;
- break;
- }
- }
-
- /*
- Let's increment the version for the file itself. We keep the current
- version when making the journal entry, because that was the version that
- was operated on. The maximum numbers for each part in the version string:
- none.99.9.9
- */
- if ($attribute == "version" && $incversion)
- {
- $version_parts = split ("\.", $value);
- $newnumofparts = $numofparts = count ($version_parts);
-
- if ($version_parts[3] >= 9)
- {
- $version_parts[3] = 0;
- $version_parts[2]++;
- $version_parts_3_update = 1;
- }
- elseif (isset ($version_parts[3]))
- {
- $version_parts[3]++;
- }
-
- if ($version_parts[2] >= 9 && $version_parts[3] == 0 && $version_parts_3_update)
- {
- $version_parts[2] = 0;
- $version_parts[1]++;
- }
-
- if ($version_parts[1] > 99)
- {
- $version_parts[1] = 0;
- $version_parts[0]++;
- }
-
- for ($i = 0; $i < $newnumofparts; $i++)
- {
- if (!isset ($version_parts[$i]))
- break;
-
- if ($i)
- $newversion .= ".";
-
- $newversion .= $version_parts[$i];
- }
-
- $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("version" => $newversion));
- }
-
- $sql .= "$attribute";
- $sql2 .= "'" . $this->db_clean ($value) . "'";
- }
-
- $sql .= ")";
- $sql2 .= ")";
-
- $sql .= $sql2;
-
- /*
- These are some special situations where we need to flush the journal entries
- or move the 'journal' entries to 'journal-deleted'. Kind of hackish, but they
- provide a consistent feel to the system
- */
- if ($operation == VFS_OPERATION_CREATED)
- {
- $flush_path = $p->fake_full_path;
- $deleteall = True;
- }
-
- if ($operation == VFS_OPERATION_COPIED || $operation == VFS_OPERATION_MOVED)
- {
- $flush_path = $state_two;
- $deleteall = False;
- }
-
- if ($flush_path)
- {
- $flush_path_parts = $this->path_parts ($flush_path, array (RELATIVE_NONE));
-
- $this->flush_journal ($flush_path_parts->fake_full_path, array ($flush_path_parts->mask), $deleteall);
- }
-
- if ($operation == VFS_OPERATION_COPIED)
- {
- /*
- We copy it going the other way as well, so both files show the operation.
- The code is a bad hack to prevent recursion. Ideally it would use VFS_OPERATION_COPIED
- */
- $this->add_journal ($state_two, array (RELATIVE_NONE), "Copied $state_one to $state_two", NULL, NULL, False);
- }
-
- if ($operation == VFS_OPERATION_MOVED)
- {
- $state_one_path_parts = $this->path_parts ($state_one, array (RELATIVE_NONE));
-
- $query = $phpgw->db->query ("UPDATE phpgw_vfs SET mime_type='journal-deleted' WHERE directory='$state_one_path_parts->fake_leading_dirs_clean' AND name='$state_one_path_parts->fake_name_clean' AND mime_type='journal'");
-
- /*
- We create the file in addition to logging the MOVED operation. This is an
- advantage because we can now search for 'Create' to see when a file was created
- */
- $this->add_journal ($state_two, array (RELATIVE_NONE), VFS_OPERATION_CREATED);
- }
-
- /* This is the SQL query we made for THIS request, remember that one? */
- $query = $phpgw->db->query ($sql, __LINE__, __FILE__);
-
- /*
- If we were to add an option of whether to keep journal entries for deleted files
- or not, it would go in the if here
- */
- if ($operation == VFS_OPERATION_DELETED)
- {
- $query = $phpgw->db->query ("UPDATE phpgw_vfs SET mime_type='journal-deleted' WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean' AND mime_type='journal'");
- }
-
- return True;
- }
-
- /*!
- @function flush_journal
- @abstract Flush journal entries for $string. Used before adding $string
- @discussion flush_journal () is an internal function and should be called from add_journal () only
- @param $string File/directory to flush journal entries of
- @param $relatives Realtivity array
- @param $deleteall Delete all types of journal entries, including the active Create entry.
- Normally you only want to delete the Create entry when replacing the file
- Note that this option does not effect $deleteonly
- @param $deletedonly Only flush 'journal-deleted' entries (created when $string was deleted)
- @result Boolean True/False
- */
-
- function flush_journal ($string, $relatives = array (RELATIVE_CURRENT), $deleteall = False, $deletedonly = False)
- {
- global $phpgw, $phpgw_info;
-
- $p = $this->path_parts ($string, array ($relatives[0]));
-
- $sql = "DELETE FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'";
-
- if (!$deleteall)
- {
- $sql .= " AND (mime_type != 'journal' AND comment != 'Created')";
- }
-
- $sql .= " AND (mime_type='journal-deleted'";
-
- if (!$deletedonly)
- {
- $sql .= " OR mime_type='journal'";
- }
-
- $sql .= ")";
-
- $query = $phpgw->db->query ($sql, __LINE__, __FILE__);
-
- if ($query)
- {
- return True;
- }
- else
- {
- return False;
- }
- }
-
- /*!
- @function get_journal
- @abstract Retrieve journal entries for $string
- @param $string File/directory to retrieve journal entries of
- @param $relatives Relativity array
- @param $type 0/False = any, 1 = 'journal', 2 = 'journal-deleted'
- @result Array of arrays of journal entries
- */
-
- function get_journal ($string, $relatives = array (RELATIVE_CURRENT), $type = False)
- {
- global $phpgw, $phpgw_info;
-
- $p = $this->path_parts ($string, array ($relatives[0]));
-
- if (!$this->acl_check ($p->fake_full_path, array ($p->mask)))
- {
- return False;
- }
-
- $sql = "SELECT * FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'";
-
- if ($type == 1)
- {
- $sql .= " AND mime_type='journal'";
- }
- elseif ($type == 2)
- {
- $sql .= " AND mime_type='journal-deleted'";
- }
- else
- {
- $sql .= " AND (mime_type='journal' OR mime_type='journal-deleted')";
- }
-
- $query = $phpgw->db->query ($sql, __LINE__, __FILE__);
-
- while ($phpgw->db->next_record ())
- {
- $rarray[] = $phpgw->db->Record;
- }
-
- return $rarray;
- }
-
- /*!
- @function path_parts
- @abstract take a real or fake pathname and return an array of its component parts
- @param $string full real or fake path
- @param $relatives Relativity array
- @param $object True returns an object instead of an array
- @param $nolinks Don't check for links (made with make_link ()). Used internally to prevent recursion
- @result $rarray/$robject Array or object containing the fake and real component parts of the path
- @discussion Returned values are:
- mask
- outside
- fake_full_path
- fake_leading_dirs
- fake_extra_path BROKEN
- fake_name
- real_full_path
- real_leading_dirs
- real_extra_path BROKEN
- real_name
- fake_full_path_clean
- fake_leading_dirs_clean
- fake_extra_path_clean BROKEN
- fake_name_clean
- real_full_path_clean
- real_leading_dirs_clean
- real_extra_path_clean BROKEN
- real_name_clean
- "clean" values are run through vfs->db_clean () and
- are safe for use in SQL queries that use key='value'
- They should be used ONLY for SQL queries, so are used
- mostly internally
- mask is either RELATIVE_NONE or RELATIVE_NONE|VFS_REAL,
- and is used internally
- outside is boolean, True if $relatives contains VFS_REAL
- */
-
- function path_parts ($string, $relatives = array (RELATIVE_CURRENT), $object = True, $nolinks = False)
- {
- global $phpgw, $phpgw_info;
- $sep = SEP;
-
- $rarray["mask"] = RELATIVE_NONE;
-
- if (!($relatives[0] & VFS_REAL))
- {
- $rarray["outside"] = False;
- $fake = True;
- }
- else
- {
- $rarray["outside"] = True;
- $rarray["mask"] |= VFS_REAL;
- }
-
- $string = $this->getabsolutepath ($string, array ($relatives[0]), $fake);
-
- if ($fake)
- {
- $base_sep = "/";
- $base = "/";
-
- $opp_base = $this->basedir . $sep;
-
- $rarray["fake_full_path"] = $string;
- }
- else
- {
- $base_sep = $sep;
- if (ereg ("^$this->basedir" . $sep, $string))
- {
- $base = $this->basedir . $sep;
- }
- else
- {
- $base = $sep;
- }
-
- $opp_base = "/";
-
- $rarray["real_full_path"] = $string;
- }
-
- /* This is needed because of substr's handling of negative lengths */
- $baselen = strlen ($base);
- $lastslashpos = strrpos ($string, $base_sep);
- $lastslashpos < $baselen ? $length = 0 : $length = $lastslashpos - $baselen;
-
- $extra_path = $rarray["fake_extra_path"] = $rarray["real_extra_path"] = substr ($string, strlen ($base), $length);
- $name = $rarray["fake_name"] = $rarray["real_name"] = substr ($string, strrpos ($string, $base_sep) + 1);
+ var $basedir;
+ var $fakebase;
+ var $relative;
+ var $working_id;
+ var $working_lid;
+ var $attributes;
+ var $override_acl;
+ var $linked_dirs;
+ var $meta_types;
- if ($fake)
- {
- $rarray["real_extra_path"] ? $dispsep = $sep : $dispsep = "";
- $rarray["real_full_path"] = $opp_base . $rarray["real_extra_path"] . $dispsep . $rarray["real_name"];
- if ($extra_path)
- {
- $rarray["fake_leading_dirs"] = $base . $extra_path;
- $rarray["real_leading_dirs"] = $opp_base . $extra_path;
- }
- elseif (strrpos ($rarray["fake_full_path"], $sep) == 0)
- {
- /* If there is only one $sep in the path, we don't want to strip it off */
- $rarray["fake_leading_dirs"] = $sep;
- $rarray["real_leading_dirs"] = substr ($opp_base, 0, strlen ($opp_base) - 1);
- }
- else
- {
- /* These strip the ending / */
- $rarray["fake_leading_dirs"] = substr ($base, 0, strlen ($base) - 1);
- $rarray["real_leading_dirs"] = substr ($opp_base, 0, strlen ($opp_base) - 1);
- }
- }
- else
- {
- $rarray["fake_full_path"] = $opp_base . $rarray["fake_extra_path"] . "/" . $rarray["fake_name"];
- if ($extra_path)
- {
- $rarray["fake_leading_dirs"] = $opp_base . $extra_path;
- $rarray["real_leading_dirs"] = $base . $extra_path;
- }
- else
- {
- $rarray["fake_leading_dirs"] = substr ($opp_base, 0, strlen ($opp_base) - 1);
- $rarray["real_leading_dirs"] = substr ($base, 0, strlen ($base) - 1);
- }
- }
-
- /* We check for linked dirs made with make_link (). This could be better, but it works */
- if (!$nolinks)
- {
- reset ($this->linked_dirs);
- while (list ($num, $link_info) = each ($this->linked_dirs))
- {
- if (ereg ("^$link_info[directory]/$link_info[name](/|$)", $rarray["fake_full_path"]))
- {
- $rarray["real_full_path"] = ereg_replace ("^$this->basedir", "", $rarray["real_full_path"]);
- $rarray["real_full_path"] = ereg_replace ("^$link_info[directory]" . SEP . "$link_info[name]", $link_info["link_directory"] . SEP . $link_info["link_name"], $rarray["real_full_path"]);
-
- $p = $this->path_parts ($rarray["real_full_path"], array (RELATIVE_NONE|VFS_REAL), True, True);
-
- $rarray["real_leading_dirs"] = $p->real_leading_dirs;
- $rarray["real_extra_path"] = $p->real_extra_path;
- $rarray["real_name"] = $p->real_name;
- }
- }
- }
-
- /*
- We have to count it before because new keys will be added,
- which would create an endless loop
+ /*!
+ @function vfs
+ @abstract constructor, sets up variables
*/
- $count = count ($rarray);
- reset ($rarray);
- for ($i = 0; (list ($key, $value) = each ($rarray)) && $i != $count; $i++)
+
+ function vfs ()
{
- $rarray[$key . "_clean"] = $this->db_clean ($value);
- }
-
- if ($object)
- {
- $robject = new path_class;
-
- reset ($rarray);
- while (list ($key, $value) = each ($rarray))
+ global $phpgw, $phpgw_info;
+
+ $this->basedir = $phpgw_info["server"]["files_dir"];
+ $this->fakebase = "/home";
+ $this->working_id = $phpgw_info["user"]["account_id"];
+ $this->working_lid = $phpgw->accounts->id2name ($this->working_id);
+ $this->now = date ("Y-m-d");
+ $this->override_acl = 0;
+
+ /*
+ File/dir attributes, each corresponding to a database field. Useful for use in loops
+ If an attribute was added to the table, add it here and possibly add it to
+ set_attributes ()
+ */
+
+ $this->attributes = array ("file_id", "owner_id", "createdby_id", "modifiedby_id", "created", "modified", "size", "mime_type", "deleteable", "comment", "app", "directory", "name", "link_directory", "link_name", "version");
+
+ /*
+ These are stored in the MIME-type field and should normally be ignored.
+ Adding a type here will ensure it is normally ignored, but you will have to
+ explicitly add it to acl_check (), and to any other SELECT's in this file
+ */
+
+ $this->meta_types = array ("journal", "journal-deleted");
+
+ /* We store the linked directories in an array now, so we don't have to make the SQL call again */
+
+ $query = $phpgw->db->query ("SELECT directory, name, link_directory, link_name FROM phpgw_vfs WHERE link_directory != '' AND link_name != ''" . $this->extra_sql (VFS_SQL_SELECT));
+
+ $this->linked_dirs = array ();
+ while ($phpgw->db->next_record ())
{
- $robject->$key = $value;
+ $this->linked_dirs[] = $phpgw->db->Record;
}
}
-
-/*
- echo "
fake_full_path: $rarray[fake_full_path]
-
fake_leading_dirs: $rarray[fake_leading_dirs]
-
fake_extra_path: $rarray[fake_extra_path]
-
fake_name: $rarray[fake_name]
-
real_full_path: $rarray[real_full_path]
-
real_leading_dirs: $rarray[real_leading_dirs]
-
real_extra_path: $rarray[real_extra_path]
-
real_name: $rarray[real_name]";
-*/
-
- if ($object)
+
+ /*!
+ @function set_relative
+ @abstract Set path relativity
+ @param $mask Relative bitmask (see RELATIVE_ defines)
+ */
+
+ function set_relative ($mask)
{
- return ($robject);
+ if (!$mask)
+ {
+ unset ($this->relative);
+ }
+ else
+ {
+ $this->relative = $mask;
+ }
}
- else
+
+ /*!
+ @function get_relative
+ @abstract Return relativity bitmask
+ @discussion Returns relativity bitmask, or the default of "completely relative" if unset
+ */
+
+ function get_relative ()
{
- return ($rarray);
+ if (isset ($this->relative))
+ {
+ return $this->relative;
+ }
+ else
+ {
+ return RELATIVE_ALL;
+ }
}
- }
-
- /*!
- @function getabsolutepath
- @abstract get the absolute path
- @param $target defaults to False, directory/file to get path of, relative to $relatives[0]
- @param $mask Relativity bitmask (see RELATIVE_ defines). RELATIVE_CURRENT means use $this->relative
- @param $fake Returns the "fake" path, ie /home/user/dir/file (not always possible. use path_parts () instead)
- @result $basedir Full fake or real path
- */
-
- function getabsolutepath ($target = False, $relatives = array (RELATIVE_CURRENT), $fake = True)
- {
- global $phpgw, $phpgw_info;
-
- $currentdir = $this->pwd (False);
-
- if (!is_array ($relatives))
+
+ /*!
+ @function sanitize
+ @abstract Removes leading .'s from $string
+ @discussion You should not pass all filenames through sanitize () unless you plan on rejecting
+ .files. Instead, pass the name through securitycheck () first, and if it fails,
+ pass it through sanitize
+ @param $string string to sanitize
+ @result $string without it's leading .'s
+ */
+
+ function sanitize ($string)
{
- $relatives = array (RELATIVE_CURRENT);
+ global $phpgw, $phpgw_info;
+
+ /* We use path_parts () just to parse the string, not translate paths */
+ $p = $this->path_parts ($string, array (RELATIVE_NONE));
+
+ return (ereg_replace ("^\.+", "", $p->fake_name));
}
-
- /* If they supply just VFS_REAL, we assume they want current relativity */
- if ($relatives[0] == VFS_REAL)
+
+ /*!
+ @function securitycheck
+ @abstract Security check function
+ @discussion Checks for basic violations such as ..
+ If securitycheck () fails, run your string through vfs->sanitize ()
+ @param $string string to check security of
+ @result Boolean True/False. True means secure, False means insecure
+ */
+
+ function securitycheck ($string)
{
- $relatives[0] |= RELATIVE_CURRENT;
- }
-
- if (!$this->securitycheck ($target))
- {
- return False;
- }
-
- if ($relatives[0] & RELATIVE_NONE)
- {
- return $target;
- }
-
- if ($fake)
- {
- $sep = "/";
- }
- else
- {
- $sep = SEP;
- }
-
- /* if RELATIVE_CURRENT, retrieve the current mask */
- if ($relatives[0] & RELATIVE_CURRENT)
- {
- $mask = $relatives[0];
- /* Respect any additional masks by re-adding them after retrieving the current mask*/
- $relatives[0] = $this->get_relative () + ($mask - RELATIVE_CURRENT);
- }
-
- if ($fake)
- {
- $basedir = "/";
- }
- else
- {
- $basedir = $this->basedir . $sep;
-
- /* This allows all requests to use /'s */
- $target = preg_replace ("|/|", $sep, $target);
- }
-
- if (($relatives[0] & RELATIVE_PATH) && $currentdir)
- {
- $basedir = $basedir . $currentdir . $sep;
- }
- elseif (($relatives[0] & RELATIVE_USER) || ($relatives[0] & RELATIVE_USER_APP))
- {
- $basedir = $basedir . $this->fakebase . $sep;
- }
-
- if ($relatives[0] & RELATIVE_CURR_USER)
- {
- $basedir = $basedir . $this->working_lid . $sep;
- }
-
- if (($relatives[0] & RELATIVE_USER) || ($relatives[0] & RELATIVE_USER_APP))
- {
- $basedir = $basedir . $phpgw_info["user"]["account_lid"] . $sep;
- }
-
- if ($relatives[0] & RELATIVE_USER_APP)
- {
- $basedir = $basedir . "." . $phpgw_info["flags"]["currentapp"] . $sep;
- }
-
- /* Don't add target if it's a /, just for aesthetics */
- if ($target && $target != $sep)
- $basedir = $basedir . $target;
-
- /* Let's not return // */
- while (ereg ($sep . $sep, $basedir))
- {
- $basedir = ereg_replace ($sep . $sep, $sep, $basedir);
- }
-
- $basedir = ereg_replace ("$sep$", "", $basedir);
-
- return $basedir;
- }
-
- /*!
- @function acl_check
- @abstract Check ACL access to $file for $phpgw_info["user"]["account_id"];
- @param $file File to check access of
- @param $relatives Standard relativity array
- @param $operation Operation to check access to. In the form of a PHPGW_ACL defines bitmask. Default is read
- @param $must_exist Boolean. Set to True if $file must exist. Otherwise, we check the parent directory as well
- @result Boolean. True if access is ok, False otherwise
- */
-
- function acl_check ($file, $relatives = array (RELATIVE_CURRENT), $operation = PHPGW_ACL_READ, $must_exist = False)
- {
- global $phpgw, $phpgw_info;
-
- /* Accommodate special situations */
- if ($this->override_acl)
- {
- return True;
- }
-
- $account_id = $phpgw_info["user"]["account_id"];
- $account_lid = $phpgw->accounts->id2name ($phpgw_info["user"]["account_id"]);
-
- $p = $this->path_parts ($file, array ($relatives[0]));
-
- /* Temporary, until we get symlink type files set up */
- if ($p->outside)
- {
- return True;
- }
-
- /* If the file doesn't exist, we get ownership from the parent directory */
- if (!$this->file_exists ($p->fake_full_path, array ($p->mask)))
- {
- if ($must_exist)
+ if (substr ($string, 0, 1) == "\\" || strstr ($string, "..") || strstr ($string, "\\..") || strstr ($string, ".\\."))
{
return False;
}
-
- $file = $p->fake_leading_dirs;
- $p2 = $this->path_parts ($file, array ($p->mask));
-
- if (!$this->file_exists ($file, array ($p->mask)))
+ else
+ {
+ return True;
+ }
+ }
+
+ /*!
+ @function db_clean
+ @abstract Clean $string for use in database queries
+ @param $string String to clean
+ @result Cleaned version of $string
+ */
+
+ function db_clean ($string)
+ {
+ $string = ereg_replace ("'", "\'", $string);
+
+ return $string;
+ }
+
+ /*!
+ @function extra_sql
+ @abstract Return extra SQL code that should be appended to certain queries
+ @param $query_type The type of query to get extra SQL code for, in the form of a VFS_SQL define
+ @result Extra SQL code
+ */
+
+ function extra_sql ($query_type = VFS_SQL_SELECT)
+ {
+ global $phpgw, $phpgw_info;
+
+ if ($query_type == VFS_SQL_SELECT || $query_type == VFS_SQL_DELETE || $query_type = VFS_SQL_UPDATE)
+ {
+ $sql = " AND ((";
+
+ reset ($this->meta_types);
+ while (list ($num, $type) = each ($this->meta_types))
+ {
+ if ($num)
+ $sql .= " AND ";
+
+ $sql .= "mime_type != '$type'";
+ }
+
+ $sql .= ") OR mime_type IS NULL)";
+ }
+
+ return ($sql);
+ }
+
+ /*!
+ @function add_journal
+ @abstract Add a journal entry after (or before) completing an operation,
+ and increment the version number. This function should be used internally only
+ @discussion Note that $state_one and $state_two are ignored for some VFS_OPERATION's, for others
+ they are required. They are ignored for any "custom" operation
+ The two operations that require $state_two:
+ $operation $state_two
+ VFS_OPERATION_COPIED fake_full_path of copied to
+ VFS_OPERATION_MOVED fake_full_path of moved to
+
+ If deleting, you must call add_journal () before you delete the entry from the database
+ @param $string File or directory to add entry for
+ @param $relatives Relativity array
+ @param $operation The operation that was performed. Either a VFS_OPERATION define or
+ a non-integer descriptive text string
+ @param $state_one The first "state" of the file or directory. Can be a file name, size,
+ location, whatever is appropriate for the specific operation
+ @param $state_two The second "state" of the file or directory
+ @param $incversion Boolean True/False. Increment the version for the file? Note that this is
+ handled automatically for the VFS_OPERATION defines.
+ i.e. VFS_OPERATION_EDITED would increment the version, VFS_OPERATION_COPIED
+ would not
+ @result Boolean True/False
+ */
+
+ function add_journal ($string, $relatives = array (RELATIVE_CURRENT), $operation, $state_one, $state_two, $incversion = True)
+ {
+ global $phpgw, $phpgw_info;
+
+ $account_id = $phpgw_info["user"]["account_id"];
+
+ $p = $this->path_parts ($string, array ($relatives[0]));
+
+ /* We check that they have some sort of access to the file other than read */
+ if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_WRITE) && !$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_EDIT) && !$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_DELETE))
{
return False;
}
+
+ if (!$this->file_exists ($p->fake_full_path, array ($p->mask)))
+ {
+ return False;
+ }
+
+ $ls_array = $this->ls ($p->fake_full_path, array ($p->mask), False, False, True);
+ $file_array = $ls_array[0];
+
+ $sql = "INSERT INTO phpgw_vfs (";
+ $sql2 .= " VALUES (";
+
+ for ($i = 0; list ($attribute, $value) = each ($file_array); $i++)
+ {
+ if ($attribute == "file_id")
+ {
+ continue;
+ }
+
+ if ($i > 1)
+ {
+ $sql .= ", ";
+ $sql2 .= ", ";
+ }
+
+ if ($attribute == "owner_id")
+ {
+ $value = $account_id;
+ }
+
+ if ($attribute == "created")
+ {
+ $value = $this->now;
+ }
+
+ if ($attribute == "mime_type")
+ {
+ $value = "journal";
+ }
+
+ if ($attribute == "comment")
+ {
+ switch ($operation)
+ {
+ case VFS_OPERATION_CREATED:
+ $value = "Created";
+ $incversion = True;
+ break;
+ case VFS_OPERATION_EDITED:
+ $value = "Edited";
+ $incversion = True;
+ break;
+ case VFS_OPERATION_EDITED_COMMENT:
+ $value = "Edited comment";
+ $incversion = False;
+ break;
+ case VFS_OPERATION_COPIED:
+ if (!$state_one)
+ {
+ $state_one = $p->fake_full_path;
+ }
+ if (!$state_two)
+ {
+ return False;
+ }
+ $value = "Copied $state_one to $state_two";
+ $incversion = False;
+ break;
+ case VFS_OPERATION_MOVED:
+ if (!$state_one)
+ {
+ $state_one = $p->fake_full_path;
+ }
+ if (!$state_two)
+ {
+ return False;
+ }
+ $value = "Moved $state_one to $state_two";
+ $incversion = False;
+ break;
+ case VFS_OPERATION_DELETED:
+ $value = "Deleted";
+ $incversion = False;
+ break;
+ default:
+ $value = $operation;
+ break;
+ }
+ }
+
+ /*
+ Let's increment the version for the file itself. We keep the current
+ version when making the journal entry, because that was the version that
+ was operated on. The maximum numbers for each part in the version string:
+ none.99.9.9
+ */
+ if ($attribute == "version" && $incversion)
+ {
+ $version_parts = split ("\.", $value);
+ $newnumofparts = $numofparts = count ($version_parts);
+
+ if ($version_parts[3] >= 9)
+ {
+ $version_parts[3] = 0;
+ $version_parts[2]++;
+ $version_parts_3_update = 1;
+ }
+ elseif (isset ($version_parts[3]))
+ {
+ $version_parts[3]++;
+ }
+
+ if ($version_parts[2] >= 9 && $version_parts[3] == 0 && $version_parts_3_update)
+ {
+ $version_parts[2] = 0;
+ $version_parts[1]++;
+ }
+
+ if ($version_parts[1] > 99)
+ {
+ $version_parts[1] = 0;
+ $version_parts[0]++;
+ }
+
+ for ($i = 0; $i < $newnumofparts; $i++)
+ {
+ if (!isset ($version_parts[$i]))
+ {
+ break;
+ }
+
+ if ($i)
+ {
+ $newversion .= ".";
+ }
+
+ $newversion .= $version_parts[$i];
+ }
+
+ $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("version" => $newversion));
+ }
+
+ $sql .= "$attribute";
+ $sql2 .= "'" . $this->db_clean ($value) . "'";
+ }
+
+ $sql .= ")";
+ $sql2 .= ")";
+
+ $sql .= $sql2;
+
+ /*
+ These are some special situations where we need to flush the journal entries
+ or move the 'journal' entries to 'journal-deleted'. Kind of hackish, but they
+ provide a consistent feel to the system
+ */
+ if ($operation == VFS_OPERATION_CREATED)
+ {
+ $flush_path = $p->fake_full_path;
+ $deleteall = True;
+ }
+
+ if ($operation == VFS_OPERATION_COPIED || $operation == VFS_OPERATION_MOVED)
+ {
+ $flush_path = $state_two;
+ $deleteall = False;
+ }
+
+ if ($flush_path)
+ {
+ $flush_path_parts = $this->path_parts ($flush_path, array (RELATIVE_NONE));
+
+ $this->flush_journal ($flush_path_parts->fake_full_path, array ($flush_path_parts->mask), $deleteall);
+ }
+
+ if ($operation == VFS_OPERATION_COPIED)
+ {
+ /*
+ We copy it going the other way as well, so both files show the operation.
+ The code is a bad hack to prevent recursion. Ideally it would use VFS_OPERATION_COPIED
+ */
+ $this->add_journal ($state_two, array (RELATIVE_NONE), "Copied $state_one to $state_two", NULL, NULL, False);
+ }
+
+ if ($operation == VFS_OPERATION_MOVED)
+ {
+ $state_one_path_parts = $this->path_parts ($state_one, array (RELATIVE_NONE));
+
+ $query = $phpgw->db->query ("UPDATE phpgw_vfs SET mime_type='journal-deleted' WHERE directory='$state_one_path_parts->fake_leading_dirs_clean' AND name='$state_one_path_parts->fake_name_clean' AND mime_type='journal'");
+
+ /*
+ We create the file in addition to logging the MOVED operation. This is an
+ advantage because we can now search for 'Create' to see when a file was created
+ */
+ $this->add_journal ($state_two, array (RELATIVE_NONE), VFS_OPERATION_CREATED);
+ }
+
+ /* This is the SQL query we made for THIS request, remember that one? */
+ $query = $phpgw->db->query ($sql, __LINE__, __FILE__);
+
+ /*
+ If we were to add an option of whether to keep journal entries for deleted files
+ or not, it would go in the if here
+ */
+ if ($operation == VFS_OPERATION_DELETED)
+ {
+ $query = $phpgw->db->query ("UPDATE phpgw_vfs SET mime_type='journal-deleted' WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean' AND mime_type='journal'");
+ }
+
+ return True;
}
- else
+
+ /*!
+ @function flush_journal
+ @abstract Flush journal entries for $string. Used before adding $string
+ @discussion flush_journal () is an internal function and should be called from add_journal () only
+ @param $string File/directory to flush journal entries of
+ @param $relatives Realtivity array
+ @param $deleteall Delete all types of journal entries, including the active Create entry.
+ Normally you only want to delete the Create entry when replacing the file
+ Note that this option does not effect $deleteonly
+ @param $deletedonly Only flush 'journal-deleted' entries (created when $string was deleted)
+ @result Boolean True/False
+ */
+
+ function flush_journal ($string, $relatives = array (RELATIVE_CURRENT), $deleteall = False, $deletedonly = False)
{
- $p2 = $p;
- }
-
- /* Read access is always allowed here, but nothing else is */
- if ($file == "/" || $file == $this->fakebase)
- {
- if ($operation == PHPGW_ACL_READ)
+ global $phpgw, $phpgw_info;
+
+ $p = $this->path_parts ($string, array ($relatives[0]));
+
+ $sql = "DELETE FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'";
+
+ if (!$deleteall)
+ {
+ $sql .= " AND (mime_type != 'journal' AND comment != 'Created')";
+ }
+
+ $sql .= " AND (mime_type='journal-deleted'";
+
+ if (!$deletedonly)
+ {
+ $sql .= " OR mime_type='journal'";
+ }
+
+ $sql .= ")";
+
+ $query = $phpgw->db->query ($sql, __LINE__, __FILE__);
+
+ if ($query)
{
return True;
}
@@ -938,1267 +554,1677 @@ class vfs
return False;
}
}
-
- /*
- We don't use ls () to get owner_id as we normally would,
- because ls () calls acl_check (), which would create an infinite loop
- */
- $query = $phpgw->db->query ("SELECT owner_id FROM phpgw_vfs WHERE directory='$p2->fake_leading_dirs_clean' AND name='$p2->fake_name_clean'" . $this->extra_sql (VFS_SQL_SELECT), __LINE__, __FILE__);
- $phpgw->db->next_record ();
- $group_id = $phpgw->db->Record["owner_id"];
-
- /* They always have access to their own files */
- if ($group_id == $account_id)
- {
- return True;
- }
-
- /* Check if they're in the group. If so, they have access */
- $memberships = $phpgw->accounts->membership ($account_id);
-
- reset ($memberships);
- while (list ($num, $group_array) = each ($memberships))
- {
- if ($group_id == $phpgw->accounts->name2id ($group_array["account_name"]))
- {
- $group_ok = 1;
- break;
- }
- }
-
- if (!$group_id)
- {
- if (!$group_id = $this->account_id)
- {
- $group_id = 0;
- }
- }
-
- $acl = CreateObject ("phpgwapi.acl", $group_id);
- $acl->account_id = $group_id;
- $acl->read_repository ();
-
- $rights = $acl->get_rights ($account_id);
- if ($rights & $operation)
- {
- return True;
- }
- elseif (!$rights && $group_ok)
- {
- return True;
- }
- else
- {
- return False;
- }
- }
- /*!
- @function cd
- @abstract Change directory
- @discussion To cd to the files root "/", use cd ("/", False, array (RELATIVE_NONE));
- @param $target default "/". directory to cd into. if "/" and $relative is True, uses "/home/";
- @param $relative default True/relative means add target to current path, else pass $relative as mask to getabsolutepath()
- */
-
- function cd ($target = "/", $relative = True, $relatives = array (RELATIVE_CURRENT))
- {
- global $phpgw, $phpgw_info;
-
- if ($relatives[0] & VFS_REAL)
+ /*!
+ @function get_journal
+ @abstract Retrieve journal entries for $string
+ @param $string File/directory to retrieve journal entries of
+ @param $relatives Relativity array
+ @param $type 0/False = any, 1 = 'journal', 2 = 'journal-deleted'
+ @result Array of arrays of journal entries
+ */
+
+ function get_journal ($string, $relatives = array (RELATIVE_CURRENT), $type = False)
{
- $sep = SEP;
- }
- else
- {
- $sep = "/";
- }
-
- if ($relative == "relative" || $relative == True)
- {
- /* if $target is "/" and $relative is set, we cd to the user/group home dir */
- if ($target == "/")
+ global $phpgw, $phpgw_info;
+
+ $p = $this->path_parts ($string, array ($relatives[0]));
+
+ if (!$this->acl_check ($p->fake_full_path, array ($p->mask)))
{
- $relatives[0] = RELATIVE_USER;
- $basedir = $this->getabsolutepath (False, array ($relatives[0]), True);
+ return False;
+ }
+
+ $sql = "SELECT * FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'";
+
+ if ($type == 1)
+ {
+ $sql .= " AND mime_type='journal'";
+ }
+ elseif ($type == 2)
+ {
+ $sql .= " AND mime_type='journal-deleted'";
}
else
{
- $currentdir = $phpgw->common->appsession ();
- $basedir = $this->getabsolutepath ($currentdir . $sep . $target, array ($relatives[0]), True);
+ $sql .= " AND (mime_type='journal' OR mime_type='journal-deleted')";
}
- }
- else
- {
- $basedir = $this->getabsolutepath ($target, array ($relatives[0]));
- }
-
- $phpgw->common->appsession ($basedir);
-
- return True;
- }
-
- /*!
- @function pwd
- @abstract current working dir
- @param $full default True returns full fake path, else just the extra dirs (false strips the leading /)
- @result $currentdir currentdir
- */
-
- function pwd ($full = True)
- {
- global $phpgw;
-
- $currentdir = $phpgw->common->appsession ();
-
- if (!$full)
- {
- $currentdir = ereg_replace ("^/", "", $currentdir);
- }
-
- if ($currentdir == "" && $full)
- {
- $currentdir = "/";
- }
-
- return $currentdir;
- }
-
- /*!
- @function read
- @abstract return file contents
- @param $file filename
- @param $relatives Relativity array
- @result $contents Contents of $file, or False if file cannot be read
- */
-
- function read ($file, $relatives = array (RELATIVE_CURRENT))
- {
- global $phpgw;
- global $phpgw_info;
-
- $p = $this->path_parts ($file, array ($relatives[0]));
-
- if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_READ))
- {
- return False;
- }
-
- if ($fp = fopen ($p->real_full_path, "r"))
- {
- $contents = fread ($fp, filesize ($p->real_full_path));
- fclose ($fp);
-
- return $contents;
- }
- else
- {
- return False;
- }
- }
-
- /*!
- @function write
- @abstract write to a file
- @param $file file name
- @param $relatives Relativity array
- @param $contents contents
- @result Boolean True/False
- */
-
- function write ($file, $relatives = array (RELATIVE_CURRENT), $contents)
- {
- global $phpgw;
- global $phpgw_info;
-
- $p = $this->path_parts ($file, array ($relatives[0]));
-
- if ($this->file_exists ($p->fake_full_path, array ($p->mask)))
- {
- $acl_operation = PHPGW_ACL_EDIT;
- $journal_operation = VFS_OPERATION_EDITED;
- }
- else
- {
- $acl_operation = PHPGW_ACL_ADD;
- }
-
- if (!$this->acl_check ($p->fake_full_path, array ($p->mask), $acl_operation))
- {
- return False;
- }
-
- umask(000);
-
- /*
- If $file doesn't exist, touch () creates both the file and the database entry
- If $file does exist, touch () sets the modification time and modified by
- */
- $this->touch ($p->fake_full_path, array ($p->mask));
-
- if ($fp = fopen ($p->real_full_path, "w"))
- {
- fwrite ($fp, $contents, strlen ($contents));
- fclose ($fp);
-
- $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("size" => $this->get_size ($p->real_full_path, array (RELATIVE_NONE|VFS_REAL))));
-
- if ($journal_operation)
+
+ $query = $phpgw->db->query ($sql, __LINE__, __FILE__);
+
+ while ($phpgw->db->next_record ())
{
- $this->add_journal ($p->fake_full_path, array ($p->mask), $journal_operation);
+ $rarray[] = $phpgw->db->Record;
+ }
+
+ return $rarray;
+ }
+
+ /*!
+ @function path_parts
+ @abstract take a real or fake pathname and return an array of its component parts
+ @param $string full real or fake path
+ @param $relatives Relativity array
+ @param $object True returns an object instead of an array
+ @param $nolinks Don't check for links (made with make_link ()). Used internally to prevent recursion
+ @result $rarray/$robject Array or object containing the fake and real component parts of the path
+ @discussion Returned values are:
+ mask
+ outside
+ fake_full_path
+ fake_leading_dirs
+ fake_extra_path BROKEN
+ fake_name
+ real_full_path
+ real_leading_dirs
+ real_extra_path BROKEN
+ real_name
+ fake_full_path_clean
+ fake_leading_dirs_clean
+ fake_extra_path_clean BROKEN
+ fake_name_clean
+ real_full_path_clean
+ real_leading_dirs_clean
+ real_extra_path_clean BROKEN
+ real_name_clean
+ "clean" values are run through vfs->db_clean () and
+ are safe for use in SQL queries that use key='value'
+ They should be used ONLY for SQL queries, so are used
+ mostly internally
+ mask is either RELATIVE_NONE or RELATIVE_NONE|VFS_REAL,
+ and is used internally
+ outside is boolean, True if $relatives contains VFS_REAL
+ */
+
+ function path_parts ($string, $relatives = array (RELATIVE_CURRENT), $object = True, $nolinks = False)
+ {
+ global $phpgw, $phpgw_info;
+ $sep = SEP;
+
+ $rarray["mask"] = RELATIVE_NONE;
+
+ if (!($relatives[0] & VFS_REAL))
+ {
+ $rarray["outside"] = False;
+ $fake = True;
}
-
+ else
+ {
+ $rarray["outside"] = True;
+ $rarray["mask"] |= VFS_REAL;
+ }
+
+ $string = $this->getabsolutepath ($string, array ($relatives[0]), $fake);
+
+ if ($fake)
+ {
+ $base_sep = "/";
+ $base = "/";
+
+ $opp_base = $this->basedir . $sep;
+
+ $rarray["fake_full_path"] = $string;
+ }
+ else
+ {
+ $base_sep = $sep;
+ if (ereg ("^$this->basedir" . $sep, $string))
+ {
+ $base = $this->basedir . $sep;
+ }
+ else
+ {
+ $base = $sep;
+ }
+
+ $opp_base = "/";
+
+ $rarray["real_full_path"] = $string;
+ }
+
+ /* This is needed because of substr's handling of negative lengths */
+ $baselen = strlen ($base);
+ $lastslashpos = strrpos ($string, $base_sep);
+ $lastslashpos < $baselen ? $length = 0 : $length = $lastslashpos - $baselen;
+
+ $extra_path = $rarray["fake_extra_path"] = $rarray["real_extra_path"] = substr ($string, strlen ($base), $length);
+ $name = $rarray["fake_name"] = $rarray["real_name"] = substr ($string, strrpos ($string, $base_sep) + 1);
+
+ if ($fake)
+ {
+ $rarray["real_extra_path"] ? $dispsep = $sep : $dispsep = "";
+ $rarray["real_full_path"] = $opp_base . $rarray["real_extra_path"] . $dispsep . $rarray["real_name"];
+ if ($extra_path)
+ {
+ $rarray["fake_leading_dirs"] = $base . $extra_path;
+ $rarray["real_leading_dirs"] = $opp_base . $extra_path;
+ }
+ elseif (strrpos ($rarray["fake_full_path"], $sep) == 0)
+ {
+ /* If there is only one $sep in the path, we don't want to strip it off */
+ $rarray["fake_leading_dirs"] = $sep;
+ $rarray["real_leading_dirs"] = substr ($opp_base, 0, strlen ($opp_base) - 1);
+ }
+ else
+ {
+ /* These strip the ending / */
+ $rarray["fake_leading_dirs"] = substr ($base, 0, strlen ($base) - 1);
+ $rarray["real_leading_dirs"] = substr ($opp_base, 0, strlen ($opp_base) - 1);
+ }
+ }
+ else
+ {
+ $rarray["fake_full_path"] = $opp_base . $rarray["fake_extra_path"] . "/" . $rarray["fake_name"];
+ if ($extra_path)
+ {
+ $rarray["fake_leading_dirs"] = $opp_base . $extra_path;
+ $rarray["real_leading_dirs"] = $base . $extra_path;
+ }
+ else
+ {
+ $rarray["fake_leading_dirs"] = substr ($opp_base, 0, strlen ($opp_base) - 1);
+ $rarray["real_leading_dirs"] = substr ($base, 0, strlen ($base) - 1);
+ }
+ }
+
+ /* We check for linked dirs made with make_link (). This could be better, but it works */
+ if (!$nolinks)
+ {
+ reset ($this->linked_dirs);
+ while (list ($num, $link_info) = each ($this->linked_dirs))
+ {
+ if (ereg ("^$link_info[directory]/$link_info[name](/|$)", $rarray["fake_full_path"]))
+ {
+ $rarray["real_full_path"] = ereg_replace ("^$this->basedir", "", $rarray["real_full_path"]);
+ $rarray["real_full_path"] = ereg_replace ("^$link_info[directory]" . SEP . "$link_info[name]", $link_info["link_directory"] . SEP . $link_info["link_name"], $rarray["real_full_path"]);
+
+ $p = $this->path_parts ($rarray["real_full_path"], array (RELATIVE_NONE|VFS_REAL), True, True);
+
+ $rarray["real_leading_dirs"] = $p->real_leading_dirs;
+ $rarray["real_extra_path"] = $p->real_extra_path;
+ $rarray["real_name"] = $p->real_name;
+ }
+ }
+ }
+
+ /*
+ We have to count it before because new keys will be added,
+ which would create an endless loop
+ */
+ $count = count ($rarray);
+ reset ($rarray);
+ for ($i = 0; (list ($key, $value) = each ($rarray)) && $i != $count; $i++)
+ {
+ $rarray[$key . "_clean"] = $this->db_clean ($value);
+ }
+
+ if ($object)
+ {
+ $robject = new path_class;
+
+ reset ($rarray);
+ while (list ($key, $value) = each ($rarray))
+ {
+ $robject->$key = $value;
+ }
+ }
+
+ /*
+ echo "
fake_full_path: $rarray[fake_full_path]
+
fake_leading_dirs: $rarray[fake_leading_dirs]
+
fake_extra_path: $rarray[fake_extra_path]
+
fake_name: $rarray[fake_name]
+
real_full_path: $rarray[real_full_path]
+
real_leading_dirs: $rarray[real_leading_dirs]
+
real_extra_path: $rarray[real_extra_path]
+
real_name: $rarray[real_name]";
+ */
+
+ if ($object)
+ {
+ return ($robject);
+ }
+ else
+ {
+ return ($rarray);
+ }
+ }
+
+ /*!
+ @function getabsolutepath
+ @abstract get the absolute path
+ @param $target defaults to False, directory/file to get path of, relative to $relatives[0]
+ @param $mask Relativity bitmask (see RELATIVE_ defines). RELATIVE_CURRENT means use $this->relative
+ @param $fake Returns the "fake" path, ie /home/user/dir/file (not always possible. use path_parts () instead)
+ @result $basedir Full fake or real path
+ */
+
+ function getabsolutepath ($target = False, $relatives = array (RELATIVE_CURRENT), $fake = True)
+ {
+ global $phpgw, $phpgw_info;
+
+ $currentdir = $this->pwd (False);
+
+ if (!is_array ($relatives))
+ {
+ $relatives = array (RELATIVE_CURRENT);
+ }
+
+ /* If they supply just VFS_REAL, we assume they want current relativity */
+ if ($relatives[0] == VFS_REAL)
+ {
+ $relatives[0] |= RELATIVE_CURRENT;
+ }
+
+ if (!$this->securitycheck ($target))
+ {
+ return False;
+ }
+
+ if ($relatives[0] & RELATIVE_NONE)
+ {
+ return $target;
+ }
+
+ if ($fake)
+ {
+ $sep = "/";
+ }
+ else
+ {
+ $sep = SEP;
+ }
+
+ /* if RELATIVE_CURRENT, retrieve the current mask */
+ if ($relatives[0] & RELATIVE_CURRENT)
+ {
+ $mask = $relatives[0];
+ /* Respect any additional masks by re-adding them after retrieving the current mask*/
+ $relatives[0] = $this->get_relative () + ($mask - RELATIVE_CURRENT);
+ }
+
+ if ($fake)
+ {
+ $basedir = "/";
+ }
+ else
+ {
+ $basedir = $this->basedir . $sep;
+
+ /* This allows all requests to use /'s */
+ $target = preg_replace ("|/|", $sep, $target);
+ }
+
+ if (($relatives[0] & RELATIVE_PATH) && $currentdir)
+ {
+ $basedir = $basedir . $currentdir . $sep;
+ }
+ elseif (($relatives[0] & RELATIVE_USER) || ($relatives[0] & RELATIVE_USER_APP))
+ {
+ $basedir = $basedir . $this->fakebase . $sep;
+ }
+
+ if ($relatives[0] & RELATIVE_CURR_USER)
+ {
+ $basedir = $basedir . $this->working_lid . $sep;
+ }
+
+ if (($relatives[0] & RELATIVE_USER) || ($relatives[0] & RELATIVE_USER_APP))
+ {
+ $basedir = $basedir . $phpgw_info["user"]["account_lid"] . $sep;
+ }
+
+ if ($relatives[0] & RELATIVE_USER_APP)
+ {
+ $basedir = $basedir . "." . $phpgw_info["flags"]["currentapp"] . $sep;
+ }
+
+ /* Don't add target if it's a /, just for aesthetics */
+ if ($target && $target != $sep)
+ $basedir = $basedir . $target;
+
+ /* Let's not return // */
+ while (ereg ($sep . $sep, $basedir))
+ {
+ $basedir = ereg_replace ($sep . $sep, $sep, $basedir);
+ }
+
+ $basedir = ereg_replace ("$sep$", "", $basedir);
+
+ return $basedir;
+ }
+
+ /*!
+ @function acl_check
+ @abstract Check ACL access to $file for $phpgw_info["user"]["account_id"];
+ @param $file File to check access of
+ @param $relatives Standard relativity array
+ @param $operation Operation to check access to. In the form of a PHPGW_ACL defines bitmask. Default is read
+ @param $must_exist Boolean. Set to True if $file must exist. Otherwise, we check the parent directory as well
+ @result Boolean. True if access is ok, False otherwise
+ */
+
+ function acl_check ($file, $relatives = array (RELATIVE_CURRENT), $operation = PHPGW_ACL_READ, $must_exist = False)
+ {
+ global $phpgw, $phpgw_info;
+
+ /* Accommodate special situations */
+ if ($this->override_acl)
+ {
+ return True;
+ }
+
+ $account_id = $phpgw_info["user"]["account_id"];
+ $account_lid = $phpgw->accounts->id2name ($phpgw_info["user"]["account_id"]);
+
+ $p = $this->path_parts ($file, array ($relatives[0]));
+
+ /* Temporary, until we get symlink type files set up */
+ if ($p->outside)
+ {
+ return True;
+ }
+
+ /* If the file doesn't exist, we get ownership from the parent directory */
+ if (!$this->file_exists ($p->fake_full_path, array ($p->mask)))
+ {
+ if ($must_exist)
+ {
+ return False;
+ }
+
+ $file = $p->fake_leading_dirs;
+ $p2 = $this->path_parts ($file, array ($p->mask));
+
+ if (!$this->file_exists ($file, array ($p->mask)))
+ {
+ return False;
+ }
+ }
+ else
+ {
+ $p2 = $p;
+ }
+
+ /* Read access is always allowed here, but nothing else is */
+ if ($file == "/" || $file == $this->fakebase)
+ {
+ if ($operation == PHPGW_ACL_READ)
+ {
+ return True;
+ }
+ else
+ {
+ return False;
+ }
+ }
+
+ /*
+ We don't use ls () to get owner_id as we normally would,
+ because ls () calls acl_check (), which would create an infinite loop
+ */
+ $query = $phpgw->db->query ("SELECT owner_id FROM phpgw_vfs WHERE directory='$p2->fake_leading_dirs_clean' AND name='$p2->fake_name_clean'" . $this->extra_sql (VFS_SQL_SELECT), __LINE__, __FILE__);
+ $phpgw->db->next_record ();
+ $group_id = $phpgw->db->Record["owner_id"];
+
+ /* They always have access to their own files */
+ if ($group_id == $account_id)
+ {
+ return True;
+ }
+
+ /* Check if they're in the group. If so, they have access */
+ $memberships = $phpgw->accounts->membership ($account_id);
+
+ reset ($memberships);
+ while (list ($num, $group_array) = each ($memberships))
+ {
+ if ($group_id == $phpgw->accounts->name2id ($group_array["account_name"]))
+ {
+ $group_ok = 1;
+ break;
+ }
+ }
+
+ if (!$group_id)
+ {
+ if (!$group_id = $this->account_id)
+ {
+ $group_id = 0;
+ }
+ }
+
+ $acl = CreateObject ("phpgwapi.acl", $group_id);
+ $acl->account_id = $group_id;
+ $acl->read_repository ();
+
+ $rights = $acl->get_rights ($account_id);
+ if ($rights & $operation)
+ {
+ return True;
+ }
+ elseif (!$rights && $group_ok)
+ {
+ return True;
+ }
+ else
+ {
+ return False;
+ }
+ }
+
+ /*!
+ @function cd
+ @abstract Change directory
+ @discussion To cd to the files root "/", use cd ("/", False, array (RELATIVE_NONE));
+ @param $target default "/". directory to cd into. if "/" and $relative is True, uses "/home/";
+ @param $relative default True/relative means add target to current path, else pass $relative as mask to getabsolutepath()
+ */
+
+ function cd ($target = "/", $relative = True, $relatives = array (RELATIVE_CURRENT))
+ {
+ global $phpgw, $phpgw_info;
+
+ if ($relatives[0] & VFS_REAL)
+ {
+ $sep = SEP;
+ }
+ else
+ {
+ $sep = "/";
+ }
+
+ if ($relative == "relative" || $relative == True)
+ {
+ /* if $target is "/" and $relative is set, we cd to the user/group home dir */
+ if ($target == "/")
+ {
+ $relatives[0] = RELATIVE_USER;
+ $basedir = $this->getabsolutepath (False, array ($relatives[0]), True);
+ }
+ else
+ {
+ $currentdir = $phpgw->common->appsession ();
+ $basedir = $this->getabsolutepath ($currentdir . $sep . $target, array ($relatives[0]), True);
+ }
+ }
+ else
+ {
+ $basedir = $this->getabsolutepath ($target, array ($relatives[0]));
+ }
+
+ $phpgw->common->appsession ($basedir);
+
return True;
}
- else
- {
- return False;
- }
- }
-
- /*!
- @function touch
- @abstract Create blank file $file or set the modification time and modified by of $file to current time and user
- @param $file File to touch or set modifies
- @param $relatives Relativity array
- @result Boolean True/False
- */
-
- function touch ($file, $relatives = array (RELATIVE_CURRENT))
- {
- global $phpgw, $phpgw_info;
-
- $account_id = $phpgw_info["user"]["account_id"];
- $currentapp = $phpgw_info["flags"]["currentapp"];
-
- $p = $this->path_parts ($file, array ($relatives[0]));
-
- umask (000);
-
- /*
- PHP's touch function will automatically decide whether to
- create the file or set the modification time
+
+ /*!
+ @function pwd
+ @abstract current working dir
+ @param $full default True returns full fake path, else just the extra dirs (false strips the leading /)
+ @result $currentdir currentdir
*/
- $rr = touch ($p->real_full_path);
-
- if ($p->outside)
+
+ function pwd ($full = True)
{
- return $rr;
+ global $phpgw;
+
+ $currentdir = $phpgw->common->appsession ();
+
+ if (!$full)
+ {
+ $currentdir = ereg_replace ("^/", "", $currentdir);
+ }
+
+ if ($currentdir == "" && $full)
+ {
+ $currentdir = "/";
+ }
+
+ return $currentdir;
}
-
- /* We, however, have to decide this ourselves */
- if ($this->file_exists ($p->fake_full_path, array ($p->mask)))
+
+ /*!
+ @function read
+ @abstract return file contents
+ @param $file filename
+ @param $relatives Relativity array
+ @result $contents Contents of $file, or False if file cannot be read
+ */
+
+ function read ($file, $relatives = array (RELATIVE_CURRENT))
{
- if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_EDIT))
+ global $phpgw;
+ global $phpgw_info;
+
+ $p = $this->path_parts ($file, array ($relatives[0]));
+
+ if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_READ))
{
return False;
}
-
- $vr = $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("modifiedby_id" => $account_id, "modified" => date ("Y-m-d")));
- }
- else
- {
- if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_ADD))
+
+ if ($fp = fopen ($p->real_full_path, "r"))
+ {
+ $contents = fread ($fp, filesize ($p->real_full_path));
+ fclose ($fp);
+
+ return $contents;
+ }
+ else
{
return False;
}
-
- $query = $phpgw->db->query ("INSERT INTO phpgw_vfs (owner_id, directory, name) VALUES ($this->working_id, '$p->fake_leading_dirs_clean', '$p->fake_name_clean')", __LINE__, __FILE__);
-
- $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("createdby_id" => $account_id, "created" => $this->now, "size" => 0, "deleteable" => "Y", "app" => $currentapp));
- $this->correct_attributes ($p->fake_full_path, array ($p->mask));
-
- $this->add_journal ($p->fake_full_path, array ($p->mask), VFS_OPERATION_CREATED);
}
-
- if ($rr || $vr || $query)
+
+ /*!
+ @function write
+ @abstract write to a file
+ @param $file file name
+ @param $relatives Relativity array
+ @param $contents contents
+ @result Boolean True/False
+ */
+
+ function write ($file, $relatives = array (RELATIVE_CURRENT), $contents)
{
+ global $phpgw;
+ global $phpgw_info;
+
+ $p = $this->path_parts ($file, array ($relatives[0]));
+
+ if ($this->file_exists ($p->fake_full_path, array ($p->mask)))
+ {
+ $acl_operation = PHPGW_ACL_EDIT;
+ $journal_operation = VFS_OPERATION_EDITED;
+ }
+ else
+ {
+ $acl_operation = PHPGW_ACL_ADD;
+ }
+
+ if (!$this->acl_check ($p->fake_full_path, array ($p->mask), $acl_operation))
+ {
+ return False;
+ }
+
+ umask(000);
+
+ /*
+ If $file doesn't exist, touch () creates both the file and the database entry
+ If $file does exist, touch () sets the modification time and modified by
+ */
+ $this->touch ($p->fake_full_path, array ($p->mask));
+
+ if ($fp = fopen ($p->real_full_path, "w"))
+ {
+ fwrite ($fp, $contents, strlen ($contents));
+ fclose ($fp);
+
+ $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("size" => $this->get_size ($p->real_full_path, array (RELATIVE_NONE|VFS_REAL))));
+
+ if ($journal_operation)
+ {
+ $this->add_journal ($p->fake_full_path, array ($p->mask), $journal_operation);
+ }
+
+ return True;
+ }
+ else
+ {
+ return False;
+ }
+ }
+
+ /*!
+ @function touch
+ @abstract Create blank file $file or set the modification time and modified by of $file to current time and user
+ @param $file File to touch or set modifies
+ @param $relatives Relativity array
+ @result Boolean True/False
+ */
+
+ function touch ($file, $relatives = array (RELATIVE_CURRENT))
+ {
+ global $phpgw, $phpgw_info;
+
+ $account_id = $phpgw_info["user"]["account_id"];
+ $currentapp = $phpgw_info["flags"]["currentapp"];
+
+ $p = $this->path_parts ($file, array ($relatives[0]));
+
+ umask (000);
+
+ /*
+ PHP's touch function will automatically decide whether to
+ create the file or set the modification time
+ */
+ $rr = touch ($p->real_full_path);
+
+ if ($p->outside)
+ {
+ return $rr;
+ }
+
+ /* We, however, have to decide this ourselves */
+ if ($this->file_exists ($p->fake_full_path, array ($p->mask)))
+ {
+ if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_EDIT))
+ {
+ return False;
+ }
+
+ $vr = $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("modifiedby_id" => $account_id, "modified" => date ("Y-m-d")));
+ }
+ else
+ {
+ if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_ADD))
+ {
+ return False;
+ }
+
+ $query = $phpgw->db->query ("INSERT INTO phpgw_vfs (owner_id, directory, name) VALUES ($this->working_id, '$p->fake_leading_dirs_clean', '$p->fake_name_clean')", __LINE__, __FILE__);
+
+ $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("createdby_id" => $account_id, "created" => $this->now, "size" => 0, "deleteable" => "Y", "app" => $currentapp));
+ $this->correct_attributes ($p->fake_full_path, array ($p->mask));
+
+ $this->add_journal ($p->fake_full_path, array ($p->mask), VFS_OPERATION_CREATED);
+ }
+
+ if ($rr || $vr || $query)
+ {
+ return True;
+ }
+ else
+ {
+ return False;
+ }
+ }
+
+ /*!
+ @function cp
+ @abstract copy file
+ @param $from from file/directory
+ @param $to to file/directory
+ @param $relatives Relativity array
+ @result boolean True/False
+ */
+
+ function cp ($from, $to, $relatives = array (RELATIVE_CURRENT, RELATIVE_CURRENT))
+ {
+ global $phpgw;
+ global $phpgw_info;
+
+ $account_id = $phpgw_info["user"]["account_id"];
+
+ $f = $this->path_parts ($from, array ($relatives[0]));
+ $t = $this->path_parts ($to, array ($relatives[1]));
+
+ if (!$this->acl_check ($f->fake_full_path, array ($f->mask), PHPGW_ACL_READ))
+ {
+ return False;
+ }
+
+ if ($this->file_exists ($t->fake_full_path, array ($t->mask)))
+ {
+ if (!$this->acl_check ($t->fake_full_path, array ($t->mask), PHPGW_ACL_EDIT))
+ {
+ return False;
+ }
+ }
+ else
+ {
+ if (!$this->acl_check ($t->fake_full_path, array ($t->mask), PHPGW_ACL_ADD))
+ {
+ return False;
+ }
+
+ }
+
+ umask(000);
+
+ if ($this->file_type ($from, array ($relatives[0])) != "Directory")
+ {
+ if (!copy ($f->real_full_path, $t->real_full_path))
+ {
+ return False;
+ }
+
+ if ($t->outside)
+ {
+ return True;
+ }
+
+ $size = filesize ($t->real_full_path);
+
+ $ls_array = $this->ls ($f->fake_full_path, array ($f->mask), False, False, True);
+ $record = $ls_array[0];
+
+ if ($this->file_exists ($to, array ($relatives[1])))
+ {
+ $query = $phpgw->db->query ("UPDATE phpgw_vfs SET owner_id='$this->working_id', directory='$t->fake_leading_dirs_clean', name='$t->fake_name_clean' WHERE owner_id='$this->working_id' AND directory='$t->fake_leading_dirs_clean' AND name='$t->fake_name_clean'" . $this->extra_sql (VFS_SQL_UPDATE), __LINE__, __FILE__);
+
+ $this->set_attributes ($t->fake_full_path, array ($t->mask), array ("createdby_id" => $account_id, "created" => $this->now, "size" => $size, "mime_type" => $record["mime_type"], "deleteable" => $record["deleteable"], "comment" => $record["comment"], "app" => $record["app"]));
+
+ $this->add_journal ($t->fake_full_path, array ($t->mask), VFS_OPERATION_EDITED);
+ }
+ else
+ {
+ $this->touch ($t->fake_full_path, array ($t->mask));
+
+ $this->set_attributes ($t->fake_full_path, array ($t->mask), array ("createdby_id" => $account_id, "created" => $this->now, "size" => $size, "mime_type" => $record["mime_type"], "deleteable" => $record["deleteable"], "comment" => $record["comment"], "app" => $record["app"]));
+ }
+
+ $this->correct_attributes ($t->fake_full_path, array ($t->mask));
+ }
+ else /* It's a directory */
+ {
+ /* First, make the initial directory */
+ $this->mkdir ($to, array ($relatives[1]));
+
+ /* Next, we create all the directories below the initial directory */
+ $ls = $this->ls ($f->fake_full_path, array ($f->mask), True, "Directory");
+
+ while (list ($num, $entry) = each ($ls))
+ {
+ $newdir = ereg_replace ("^$f->fake_full_path", "$t->fake_full_path", $entry["directory"]);
+ $this->mkdir ("$newdir/$entry[name]", array ($t->mask));
+ }
+
+ /* Lastly, we copy the files over */
+ $ls = $this->ls ($f->fake_full_path, array ($f->mask));
+
+ while (list ($num, $entry) = each ($ls))
+ {
+ if ($entry["mime_type"] == "Directory")
+ {
+ continue;
+ }
+
+ $newdir = ereg_replace ("^$f->fake_full_path", "$t->fake_full_path", $entry["directory"]);
+ $this->cp ("$entry[directory]/$entry[name]", "$newdir/$entry[name]", array ($f->mask, $t->mask));
+ }
+ }
+
+ if (!$f->outside)
+ {
+ $this->add_journal ($f->fake_full_path, array ($f->mask), VFS_OPERATION_COPIED, NULL, $t->fake_full_path);
+ }
+
return True;
}
- else
+
+ function copy ($from, $to, $relatives = array (RELATIVE_CURRENT, RELATIVE_CURRENT))
{
- return False;
+ umask (000);
+ return $this->cp ($from, $to);
}
- }
-
- /*!
- @function cp
- @abstract copy file
- @param $from from file/directory
- @param $to to file/directory
- @param $relatives Relativity array
- @result boolean True/False
- */
-
- function cp ($from, $to, $relatives = array (RELATIVE_CURRENT, RELATIVE_CURRENT))
- {
- global $phpgw;
- global $phpgw_info;
-
- $account_id = $phpgw_info["user"]["account_id"];
-
- $f = $this->path_parts ($from, array ($relatives[0]));
- $t = $this->path_parts ($to, array ($relatives[1]));
-
- if (!$this->acl_check ($f->fake_full_path, array ($f->mask), PHPGW_ACL_READ))
+
+ /*!
+ @function mv
+ @abstract move file/directory
+ @param $from from file/directory
+ @param $to to file/directory
+ @param $relatives Relativity array
+ @result boolean True/False
+ */
+
+ function mv ($from, $to, $relatives = array (RELATIVE_CURRENT, RELATIVE_CURRENT))
{
- return False;
- }
-
- if ($this->file_exists ($t->fake_full_path, array ($t->mask)))
- {
- if (!$this->acl_check ($t->fake_full_path, array ($t->mask), PHPGW_ACL_EDIT))
+ global $phpgw;
+ global $phpgw_info;
+
+ $account_id = $phpgw_info["user"]["account_id"];
+
+ $f = $this->path_parts ($from, array ($relatives[0]));
+ $t = $this->path_parts ($to, array ($relatives[1]));
+
+ if (!$this->acl_check ($f->fake_full_path, array ($f->mask), PHPGW_ACL_READ) || !$this->acl_check ($f->fake_full_path, array ($f->mask), PHPGW_ACL_DELETE))
{
return False;
}
- }
- else
- {
+
if (!$this->acl_check ($t->fake_full_path, array ($t->mask), PHPGW_ACL_ADD))
{
return False;
}
-
- }
-
- umask(000);
-
- if ($this->file_type ($from, array ($relatives[0])) != "Directory")
- {
- if (!copy ($f->real_full_path, $t->real_full_path))
+
+ if ($this->file_exists ($t->fake_full_path, array ($t->mask)))
{
- return False;
- }
-
- if ($t->outside)
- {
- return True;
- }
-
- $size = filesize ($t->real_full_path);
-
- $ls_array = $this->ls ($f->fake_full_path, array ($f->mask), False, False, True);
- $record = $ls_array[0];
-
- if ($this->file_exists ($to, array ($relatives[1])))
- {
- $query = $phpgw->db->query ("UPDATE phpgw_vfs SET owner_id='$this->working_id', directory='$t->fake_leading_dirs_clean', name='$t->fake_name_clean' WHERE owner_id='$this->working_id' AND directory='$t->fake_leading_dirs_clean' AND name='$t->fake_name_clean'" . $this->extra_sql (VFS_SQL_UPDATE), __LINE__, __FILE__);
-
- $this->set_attributes ($t->fake_full_path, array ($t->mask), array ("createdby_id" => $account_id, "created" => $this->now, "size" => $size, "mime_type" => $record["mime_type"], "deleteable" => $record["deleteable"], "comment" => $record["comment"], "app" => $record["app"]));
-
- $this->add_journal ($t->fake_full_path, array ($t->mask), VFS_OPERATION_EDITED);
- }
- else
- {
- $this->touch ($t->fake_full_path, array ($t->mask));
-
- $this->set_attributes ($t->fake_full_path, array ($t->mask), array ("createdby_id" => $account_id, "created" => $this->now, "size" => $size, "mime_type" => $record["mime_type"], "deleteable" => $record["deleteable"], "comment" => $record["comment"], "app" => $record["app"]));
- }
-
- $this->correct_attributes ($t->fake_full_path, array ($t->mask));
- }
- else /* It's a directory */
- {
- /* First, make the initial directory */
- $this->mkdir ($to, array ($relatives[1]));
-
- /* Next, we create all the directories below the initial directory */
- $ls = $this->ls ($f->fake_full_path, array ($f->mask), True, "Directory");
-
- while (list ($num, $entry) = each ($ls))
- {
- $newdir = ereg_replace ("^$f->fake_full_path", "$t->fake_full_path", $entry["directory"]);
- $this->mkdir ("$newdir/$entry[name]", array ($t->mask));
- }
-
- /* Lastly, we copy the files over */
- $ls = $this->ls ($f->fake_full_path, array ($f->mask));
-
- while (list ($num, $entry) = each ($ls))
- {
- if ($entry["mime_type"] == "Directory")
+ if (!$this->acl_check ($t->fake_full_path, array ($t->mask), PHPGW_ACL_EDIT))
{
- continue;
+ return False;
}
-
- $newdir = ereg_replace ("^$f->fake_full_path", "$t->fake_full_path", $entry["directory"]);
- $this->cp ("$entry[directory]/$entry[name]", "$newdir/$entry[name]", array ($f->mask, $t->mask));
}
- }
-
- if (!$f->outside)
- {
- $this->add_journal ($f->fake_full_path, array ($f->mask), VFS_OPERATION_COPIED, NULL, $t->fake_full_path);
- }
-
- return True;
- }
-
- function copy ($from, $to, $relatives = array (RELATIVE_CURRENT, RELATIVE_CURRENT))
- {
- umask (000);
- return $this->cp ($from, $to);
- }
-
- /*!
- @function mv
- @abstract move file/directory
- @param $from from file/directory
- @param $to to file/directory
- @param $relatives Relativity array
- @result boolean True/False
- */
-
- function mv ($from, $to, $relatives = array (RELATIVE_CURRENT, RELATIVE_CURRENT))
- {
- global $phpgw;
- global $phpgw_info;
-
- $account_id = $phpgw_info["user"]["account_id"];
-
- $f = $this->path_parts ($from, array ($relatives[0]));
- $t = $this->path_parts ($to, array ($relatives[1]));
-
- if (!$this->acl_check ($f->fake_full_path, array ($f->mask), PHPGW_ACL_READ) || !$this->acl_check ($f->fake_full_path, array ($f->mask), PHPGW_ACL_DELETE))
- {
- return False;
- }
-
- if (!$this->acl_check ($t->fake_full_path, array ($t->mask), PHPGW_ACL_ADD))
- {
- return False;
- }
-
- if ($this->file_exists ($t->fake_full_path, array ($t->mask)))
- {
- if (!$this->acl_check ($t->fake_full_path, array ($t->mask), PHPGW_ACL_EDIT))
+
+ umask (000);
+
+ /* We can't move directories into themselves */
+ if (($this->file_type ($f->fake_full_path, array ($f->mask)) == "Directory") && ereg ("^$f->fake_full_path", $t->fake_full_path))
{
- return False;
- }
- }
-
- umask (000);
-
- /* We can't move directories into themselves */
- if (($this->file_type ($f->fake_full_path, array ($f->mask)) == "Directory") && ereg ("^$f->fake_full_path", $t->fake_full_path))
- {
- if (($t->fake_full_path == $f->fake_full_path) || substr ($t->fake_full_path, strlen ($f->fake_full_path), 1) == "/")
- {
- return False;
- }
- }
-
- if ($this->file_exists ($f->fake_full_path, array ($f->mask)))
- {
- /* We get the listing now, because it will change after we update the database */
- $ls = $this->ls ($f->fake_full_path, array ($f->mask));
-
- $this->rm ($t->fake_full_path, array ($t->mask));
-
- /*
- We add the journal entry now, before we delete. This way the mime_type
- field will be updated to 'journal-deleted' when the file is actually deleted
- */
- if (!$f->outside)
- {
- $this->add_journal ($f->fake_full_path, array ($f->mask), VFS_OPERATION_MOVED, $f->fake_full_path, $t->fake_full_path);
- }
-
- /*
- If the from file is outside, it won't have a database entry,
- so we have to touch it and find the size
- */
- if ($f->outside)
- {
- $size = filesize ($f->real_full_path);
-
- $this->touch ($t->fake_full_path, array ($t->mask));
- $query = $phpgw->db->query ("UPDATE phpgw_vfs SET size=$size WHERE directory='$t->fake_leading_dirs_clean' AND name='$t->fake_name_clean'" . $this->extra_sql (VFS_SQL_UPDATE), __LINE__, __FILE__);
- }
- elseif (!$t->outside)
- {
- $query = $phpgw->db->query ("UPDATE phpgw_vfs SET name='$t->fake_name_clean', directory='$t->fake_leading_dirs_clean' WHERE directory='$f->fake_leading_dirs_clean' AND name='$f->fake_name_clean'" . $this->extra_sql (VFS_SQL_UPDATE), __LINE__, __FILE__);
- }
-
- $this->set_attributes ($t->fake_full_path, array ($t->mask), array ("modifiedby_id" => $account_id, modified => $this->now));
- $this->correct_attributes ($t->fake_full_path, array ($t->mask));
-
- $rr = rename ($f->real_full_path, $t->real_full_path);
-
- /*
- This removes the original entry from the database
- The actual file is already deleted because of the rename () above
- */
- if ($t->outside)
- {
- $this->rm ($f->fake_full_path, $f->mask);
- }
- }
- else
- {
- return False;
- }
-
- if ($this->file_type ($t->fake_full_path, array ($t->mask)) == "Directory")
- {
- /* We got $ls from above, before we renamed the directory */
- while (list ($num, $entry) = each ($ls))
- {
- $newdir = ereg_replace ("^$f->fake_full_path", $t->fake_full_path, $entry["directory"]);
- $newdir_clean = $this->db_clean ($newdir);
-
- $query = $phpgw->db->query ("UPDATE phpgw_vfs SET directory='$newdir_clean' WHERE file_id='$entry[file_id]'" . $this->extra_sql (VFS_SQL_UPDATE), __LINE__, __FILE__);
- $this->correct_attributes ("$newdir/$entry[name]", array ($t->mask));
- }
- }
-
- $this->add_journal ($t->fake_full_path, array ($t->mask), VFS_OPERATION_MOVED, $f->fake_full_path, $t->fake_full_path);
-
- return True;
- }
-
- /*!
- @function move
- @abstract shortcut to mv
- */
-
- function move ($from, $to, $relatives = array (RELATIVE_CURRENT, RELATIVE_CURRENT))
- {
- umask (000);
- return $this->mv ($from, $to, $relatives);
- }
-
- /*!
- @function rm
- @abstract delete file/directory
- @param $string file/directory to delete
- @param $relatives Relativity array
- @result boolean True/False
- */
-
- function rm ($string, $relatives = array (RELATIVE_CURRENT))
- {
- global $phpgw;
- global $phpgw_info;
-
- $p = $this->path_parts ($string, array ($relatives[0]));
-
- if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_DELETE))
- {
- return False;
- }
-
- if (!$this->file_exists ($string, array ($relatives[0])))
- {
- $rr = unlink ($p->real_full_path);
-
- if ($rr)
- {
- return True;
- }
- else
- {
- return False;
- }
- }
-
- if ($this->file_type ($string, array ($relatives[0])) != "Directory")
- {
- $this->add_journal ($p->fake_full_path, array ($p->mask), VFS_OPERATION_DELETED);
-
- $query = $phpgw->db->query ("DELETE FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'" . $this->extra_sql (VFS_SQL_DELETE), __LINE__, __FILE__);
- $rr = unlink ($p->real_full_path);
-
- if ($query || $rr)
- {
- return True;
- }
- else
- {
- return False;
- }
- }
- else
- {
- $ls = $this->ls ($p->fake_full_path, array ($p->mask));
-
- /* First, we cycle through the entries and delete the files */
- while (list ($num, $entry) = each ($ls))
- {
- if ($entry["mime_type"] == "Directory")
+ if (($t->fake_full_path == $f->fake_full_path) || substr ($t->fake_full_path, strlen ($f->fake_full_path), 1) == "/")
{
- continue;
+ return False;
}
-
- $this->rm ("$entry[directory]/$entry[name]", array ($p->mask));
}
-
- /* Now we cycle through again and delete the directories */
- reset ($ls);
- while (list ($num, $entry) = each ($ls))
+
+ if ($this->file_exists ($f->fake_full_path, array ($f->mask)))
{
- if ($entry["mime_type"] != "Directory")
- {
- continue;
- }
-
- /* Only the best in confusing recursion */
- $this->rm ("$entry[directory]/$entry[name]", array ($p->mask));
- }
-
- /* If the directory is linked, we delete the placeholder directory */
- $ls_array = $this->ls ($p->fake_full_path, array ($p->mask), False, False, True);
- $link_info = $ls_array[0];
-
- if ($link_info["link_directory"] && $link_info["link_name"])
- {
- $path = $this->path_parts ($link_info["directory"] . "/" . $link_info["name"], array ($p->mask), True, True);
- rmdir ($path->real_full_path);
- }
-
- /* Last, we delete the directory itself */
- $this->add_journal ($p->fake_full_path, array ($p->mask), VFS_OPERATION_DELETED);
-
- $query = $phpgw->db->query ("DELETE FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'" . $this->extra_sql (VFS_SQL_DELETE), __LINE__, __FILE__);
-
- rmdir ($p->real_full_path);
-
- return True;
- }
- }
-
- /*!
- @function delete
- @abstract shortcut to rm
- */
-
- function delete ($string, $relatives = array (RELATIVE_CURRENT))
- {
- return $this->rm ($string, $relatives);
- }
-
- /*!
- @function mkdir
- @abstract make a new directory
- @param $dir Directory name
- @param $relatives Relativity array
- @result boolean True on success
- */
-
- function mkdir ($dir, $relatives = array (RELATIVE_CURRENT))
- {
- global $phpgw;
- global $phpgw_info;
-
- $account_id = $phpgw_info["user"]["account_id"];
- $currentapp = $phpgw_info["flags"]["currentapp"];
-
- $p = $this->path_parts ($dir, array ($relatives[0]));
-
- if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_ADD))
- {
- return False;
- }
-
- /* We don't allow /'s in dir names, of course */
- if (ereg ("/", $p->fake_name))
- {
- return False;
- }
-
- umask (000);
-
- if (!mkdir ($p->real_full_path, 0770))
- {
- return False;
- }
-
- if (!$this->file_exists ($p->fake_full_path, array ($p->mask)))
- {
- $query = $phpgw->db->query ("INSERT INTO phpgw_vfs (owner_id, name, directory) VALUES ($this->working_id, '$p->fake_name_clean', '$p->fake_leading_dirs_clean')", __LINE__, __FILE__);
-
- $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("createdby_id" => $account_id, "size" => 4096, "mime_type" => "Directory", "created" => $this->now, "modified" => "NULL", deleteable => "Y", "app" => $currentapp));
-
- $this->correct_attributes ($p->fake_full_path, array ($p->mask));
-
- $this->add_journal ($p->fake_full_path, array ($p->mask), VFS_OPERATION_CREATED);
- }
- else
- {
- return False;
- }
-
- return True;
- }
-
- /*!
- @function make_link
- @abstract Make a link from virtual directory $vdir to real directory $rdir
- @discussion Making a link from $vdir to $rdir will cause path_parts () to substitute $rdir for the real
- path variables when presented with $rdir
- @param $vdir Virtual dir to make link from
- @param $rdir Real dir to make link to
- @param $relatives Relativity array
- @result Boolean True/False
- */
-
- function make_link ($vdir, $rdir, $relatives = array (RELATIVE_CURRENT, RELATIVE_CURRENT))
- {
- global $phpgw;
- global $phpgw_info;
-
- $account_id = $phpgw_info["user"]["account_id"];
- $currentapp = $phpgw_info["flags"]["currentapp"];
-
- $vp = $this->path_parts ($vdir, array ($relatives[0]));
- $rp = $this->path_parts ($rdir, array ($relatives[1]));
-
- if (!$this->acl_check ($vp->fake_full_path, array ($vp->mask), PHPGW_ACL_ADD))
- {
- return False;
- }
-
- if ((!$this->file_exists ($rp->real_full_path, array ($rp->mask))) && !mkdir ($rp->real_full_path, 0770))
- {
- return False;
- }
-
- if (!$this->mkdir ($vp->fake_full_path, array ($vp->mask)))
- {
- return False;
- }
-
- $size = $this->get_size ($rp->real_full_path, array ($rp->mask));
-
- $this->set_attributes ($vp->fake_full_path, array ($vp->mask), array ("link_directory" => $rp->real_leading_dirs, "link_name" => $rp->real_name, "size" => $size));
-
- $this->correct_attributes ($vp->fake_full_path, array ($vp->mask));
-
- return True;
- }
-
- /*!
- @function set_attributes
- @abstract Update database entry for $file with the attributes in $attributes
- @param $file file/directory to update
- @param $relatives Relativity array
- @param $attributes keyed array of attributes. key is attribute name, value is attribute value
- @result Boolean True/False
- @discussion Valid attributes are:
- owner_id
- createdby_id
- modifiedby_id
- created
- modified
- size
- mime_type
- deleteable
- comment
- app
- link_directory
- link_name
- version
- */
-
- function set_attributes ($file, $relatives = array (RELATIVE_CURRENT), $attributes = array ())
- {
- global $phpgw;
- global $phpgw_info;
-
- $p = $this->path_parts ($file, array ($relatives[0]));
-
- /*
- This is kind of trivial, given that set_attributes () can change owner_id,
- size, etc.
- */
- if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_EDIT))
- {
- return False;
- }
-
- if (!$this->file_exists ($file, array ($relatives[0])))
- {
- return False;
- }
-
- /*
- All this voodoo just decides which attributes to keep, and which to update
- depending on if the attribute was supplied in the $attributes array
- */
-
- $ls_array = $this->ls ($p->fake_full_path, array ($p->mask), False, False, True);
- $record = $ls_array[0];
-
- $attribute_names = array ("owner_id", "createdby_id", "modifiedby_id", "created", "modified", "size", "mime_type", "deleteable", "comment", "app", "link_directory", "link_name", "version");
-
- while (list ($num, $attribute) = each ($attribute_names))
- {
- if (isset ($attributes[$attribute]))
- {
- $$attribute = $attributes[$attribute];
-
+ /* We get the listing now, because it will change after we update the database */
+ $ls = $this->ls ($f->fake_full_path, array ($f->mask));
+
+ $this->rm ($t->fake_full_path, array ($t->mask));
+
/*
- Indicate that the EDITED_COMMENT operation needs to be journaled,
- but only if the comment changed
+ We add the journal entry now, before we delete. This way the mime_type
+ field will be updated to 'journal-deleted' when the file is actually deleted
*/
- if ($attribute == "comment" && $attributes[$attribute] != $record[$attribute])
+ if (!$f->outside)
{
- $edited_comment = 1;
+ $this->add_journal ($f->fake_full_path, array ($f->mask), VFS_OPERATION_MOVED, $f->fake_full_path, $t->fake_full_path);
+ }
+
+ /*
+ If the from file is outside, it won't have a database entry,
+ so we have to touch it and find the size
+ */
+ if ($f->outside)
+ {
+ $size = filesize ($f->real_full_path);
+
+ $this->touch ($t->fake_full_path, array ($t->mask));
+ $query = $phpgw->db->query ("UPDATE phpgw_vfs SET size=$size WHERE directory='$t->fake_leading_dirs_clean' AND name='$t->fake_name_clean'" . $this->extra_sql (VFS_SQL_UPDATE), __LINE__, __FILE__);
+ }
+ elseif (!$t->outside)
+ {
+ $query = $phpgw->db->query ("UPDATE phpgw_vfs SET name='$t->fake_name_clean', directory='$t->fake_leading_dirs_clean' WHERE directory='$f->fake_leading_dirs_clean' AND name='$f->fake_name_clean'" . $this->extra_sql (VFS_SQL_UPDATE), __LINE__, __FILE__);
+ }
+
+ $this->set_attributes ($t->fake_full_path, array ($t->mask), array ("modifiedby_id" => $account_id, modified => $this->now));
+ $this->correct_attributes ($t->fake_full_path, array ($t->mask));
+
+ $rr = rename ($f->real_full_path, $t->real_full_path);
+
+ /*
+ This removes the original entry from the database
+ The actual file is already deleted because of the rename () above
+ */
+ if ($t->outside)
+ {
+ $this->rm ($f->fake_full_path, $f->mask);
}
}
else
{
- $$attribute = $record[$attribute];
+ return False;
}
-
- $$attribute = $this->db_clean ($$attribute);
- }
-
- $sql = "UPDATE phpgw_vfs SET ";
-
- reset ($attribute_names);
- while (list ($num, $attribute) = each ($attribute_names))
- {
- if ($num)
- $sql .= ", ";
-
- $sql .= "$attribute='" . $$attribute . "'";
- }
-
- $sql .= " WHERE file_id='$record[file_id]'";
- $sql .= $this->extra_sql (VFS_SQL_UPDATE);
-
- $query = $phpgw->db->query ($sql, __LINE__, __FILE__);
-
- if ($query)
- {
- if ($edited_comment)
+
+ if ($this->file_type ($t->fake_full_path, array ($t->mask)) == "Directory")
{
- $this->add_journal ($p->fake_full_path, array ($p->mask), VFS_OPERATION_EDITED_COMMENT);
+ /* We got $ls from above, before we renamed the directory */
+ while (list ($num, $entry) = each ($ls))
+ {
+ $newdir = ereg_replace ("^$f->fake_full_path", $t->fake_full_path, $entry["directory"]);
+ $newdir_clean = $this->db_clean ($newdir);
+
+ $query = $phpgw->db->query ("UPDATE phpgw_vfs SET directory='$newdir_clean' WHERE file_id='$entry[file_id]'" . $this->extra_sql (VFS_SQL_UPDATE), __LINE__, __FILE__);
+ $this->correct_attributes ("$newdir/$entry[name]", array ($t->mask));
+ }
}
-
+
+ $this->add_journal ($t->fake_full_path, array ($t->mask), VFS_OPERATION_MOVED, $f->fake_full_path, $t->fake_full_path);
+
return True;
}
- else
+
+ /*!
+ @function move
+ @abstract shortcut to mv
+ */
+
+ function move ($from, $to, $relatives = array (RELATIVE_CURRENT, RELATIVE_CURRENT))
{
- return False;
+ umask (000);
+ return $this->mv ($from, $to, $relatives);
}
- }
-
- /*!
- @function correct_attributes
- @abstract Set the correct attributes for $string (e.g. owner)
- @param $string File/directory to correct attributes of
- @param $relatives Relativity array
- @result Boolean True/False
- */
-
- function correct_attributes ($string, $relatives = array (RELATIVE_CURRENT))
- {
- global $phpgw;
-
- $p = $this->path_parts ($string, array ($relatives[0]));
-
- if ($p->fake_leading_dirs != $this->fakebase && $p->fake_leading_dirs != "/")
+
+ /*!
+ @function rm
+ @abstract delete file/directory
+ @param $string file/directory to delete
+ @param $relatives Relativity array
+ @result boolean True/False
+ */
+
+ function rm ($string, $relatives = array (RELATIVE_CURRENT))
{
- $ls_array = $this->ls ($p->fake_leading_dirs, array ($p->mask), False, False, True);
- $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("owner_id" => $ls_array[0]["owner_id"]));
-
- return True;
- }
- elseif (preg_match ("+^$this->fakebase\/(.*)$+U", $p->fake_full_path, $matches))
- {
- $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("owner_id" => $phpgw->accounts->name2id ($matches[1])));
-
- return True;
- }
- else
- {
- $this->set_attributes ($p->fake_full_name, array ($p->mask), array ("owner_id" => 0));
-
- return True;
- }
- }
-
- /*!
- @function file_type
- @abstract return file/dir type (MIME or other)
- @param $file File or directory path (/home/user/dir/dir2/dir3, /home/user/dir/dir2/file)
- @param $relatives Relativity array
- @result MIME type, "Directory", or nothing if MIME type is not known
- */
-
- function file_type ($file, $relatives = array (RELATIVE_CURRENT))
- {
- global $phpgw;
-
- $p = $this->path_parts ($file, array ($relatives[0]));
-
- if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_READ, True))
- {
- return False;
- }
-
- if ($p->outside)
- {
- if (is_dir ($p->real_full_path))
+ global $phpgw;
+ global $phpgw_info;
+
+ $p = $this->path_parts ($string, array ($relatives[0]));
+
+ if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_DELETE))
{
- return ("Directory");
+ return False;
}
-
+
+ if (!$this->file_exists ($string, array ($relatives[0])))
+ {
+ $rr = unlink ($p->real_full_path);
+
+ if ($rr)
+ {
+ return True;
+ }
+ else
+ {
+ return False;
+ }
+ }
+
+ if ($this->file_type ($string, array ($relatives[0])) != "Directory")
+ {
+ $this->add_journal ($p->fake_full_path, array ($p->mask), VFS_OPERATION_DELETED);
+
+ $query = $phpgw->db->query ("DELETE FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'" . $this->extra_sql (VFS_SQL_DELETE), __LINE__, __FILE__);
+ $rr = unlink ($p->real_full_path);
+
+ if ($query || $rr)
+ {
+ return True;
+ }
+ else
+ {
+ return False;
+ }
+ }
+ else
+ {
+ $ls = $this->ls ($p->fake_full_path, array ($p->mask));
+
+ /* First, we cycle through the entries and delete the files */
+ while (list ($num, $entry) = each ($ls))
+ {
+ if ($entry["mime_type"] == "Directory")
+ {
+ continue;
+ }
+
+ $this->rm ("$entry[directory]/$entry[name]", array ($p->mask));
+ }
+
+ /* Now we cycle through again and delete the directories */
+ reset ($ls);
+ while (list ($num, $entry) = each ($ls))
+ {
+ if ($entry["mime_type"] != "Directory")
+ {
+ continue;
+ }
+
+ /* Only the best in confusing recursion */
+ $this->rm ("$entry[directory]/$entry[name]", array ($p->mask));
+ }
+
+ /* If the directory is linked, we delete the placeholder directory */
+ $ls_array = $this->ls ($p->fake_full_path, array ($p->mask), False, False, True);
+ $link_info = $ls_array[0];
+
+ if ($link_info["link_directory"] && $link_info["link_name"])
+ {
+ $path = $this->path_parts ($link_info["directory"] . "/" . $link_info["name"], array ($p->mask), True, True);
+ rmdir ($path->real_full_path);
+ }
+
+ /* Last, we delete the directory itself */
+ $this->add_journal ($p->fake_full_path, array ($p->mask), VFS_OPERATION_DELETED);
+
+ $query = $phpgw->db->query ("DELETE FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'" . $this->extra_sql (VFS_SQL_DELETE), __LINE__, __FILE__);
+
+ rmdir ($p->real_full_path);
+
+ return True;
+ }
+ }
+
+ /*!
+ @function delete
+ @abstract shortcut to rm
+ */
+
+ function delete ($string, $relatives = array (RELATIVE_CURRENT))
+ {
+ return $this->rm ($string, $relatives);
+ }
+
+ /*!
+ @function mkdir
+ @abstract make a new directory
+ @param $dir Directory name
+ @param $relatives Relativity array
+ @result boolean True on success
+ */
+
+ function mkdir ($dir, $relatives = array (RELATIVE_CURRENT))
+ {
+ global $phpgw;
+ global $phpgw_info;
+
+ $account_id = $phpgw_info["user"]["account_id"];
+ $currentapp = $phpgw_info["flags"]["currentapp"];
+
+ $p = $this->path_parts ($dir, array ($relatives[0]));
+
+ if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_ADD))
+ {
+ return False;
+ }
+
+ /* We don't allow /'s in dir names, of course */
+ if (ereg ("/", $p->fake_name))
+ {
+ return False;
+ }
+
+ umask (000);
+
+ if (!mkdir ($p->real_full_path, 0770))
+ {
+ return False;
+ }
+
+ if (!$this->file_exists ($p->fake_full_path, array ($p->mask)))
+ {
+ $query = $phpgw->db->query ("INSERT INTO phpgw_vfs (owner_id, name, directory) VALUES ($this->working_id, '$p->fake_name_clean', '$p->fake_leading_dirs_clean')", __LINE__, __FILE__);
+
+ $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("createdby_id" => $account_id, "size" => 4096, "mime_type" => "Directory", "created" => $this->now, "modified" => "NULL", deleteable => "Y", "app" => $currentapp));
+
+ $this->correct_attributes ($p->fake_full_path, array ($p->mask));
+
+ $this->add_journal ($p->fake_full_path, array ($p->mask), VFS_OPERATION_CREATED);
+ }
+ else
+ {
+ return False;
+ }
+
+ return True;
+ }
+
+ /*!
+ @function make_link
+ @abstract Make a link from virtual directory $vdir to real directory $rdir
+ @discussion Making a link from $vdir to $rdir will cause path_parts () to substitute $rdir for the real
+ path variables when presented with $rdir
+ @param $vdir Virtual dir to make link from
+ @param $rdir Real dir to make link to
+ @param $relatives Relativity array
+ @result Boolean True/False
+ */
+
+ function make_link ($vdir, $rdir, $relatives = array (RELATIVE_CURRENT, RELATIVE_CURRENT))
+ {
+ global $phpgw;
+ global $phpgw_info;
+
+ $account_id = $phpgw_info["user"]["account_id"];
+ $currentapp = $phpgw_info["flags"]["currentapp"];
+
+ $vp = $this->path_parts ($vdir, array ($relatives[0]));
+ $rp = $this->path_parts ($rdir, array ($relatives[1]));
+
+ if (!$this->acl_check ($vp->fake_full_path, array ($vp->mask), PHPGW_ACL_ADD))
+ {
+ return False;
+ }
+
+ if ((!$this->file_exists ($rp->real_full_path, array ($rp->mask))) && !mkdir ($rp->real_full_path, 0770))
+ {
+ return False;
+ }
+
+ if (!$this->mkdir ($vp->fake_full_path, array ($vp->mask)))
+ {
+ return False;
+ }
+
+ $size = $this->get_size ($rp->real_full_path, array ($rp->mask));
+
+ $this->set_attributes ($vp->fake_full_path, array ($vp->mask), array ("link_directory" => $rp->real_leading_dirs, "link_name" => $rp->real_name, "size" => $size));
+
+ $this->correct_attributes ($vp->fake_full_path, array ($vp->mask));
+
+ return True;
+ }
+
+ /*!
+ @function set_attributes
+ @abstract Update database entry for $file with the attributes in $attributes
+ @param $file file/directory to update
+ @param $relatives Relativity array
+ @param $attributes keyed array of attributes. key is attribute name, value is attribute value
+ @result Boolean True/False
+ @discussion Valid attributes are:
+ owner_id
+ createdby_id
+ modifiedby_id
+ created
+ modified
+ size
+ mime_type
+ deleteable
+ comment
+ app
+ link_directory
+ link_name
+ version
+ */
+
+ function set_attributes ($file, $relatives = array (RELATIVE_CURRENT), $attributes = array ())
+ {
+ global $phpgw;
+ global $phpgw_info;
+
+ $p = $this->path_parts ($file, array ($relatives[0]));
+
/*
- We don't return an empty string here, because it may still match with a database query
- because of linked directories
+ This is kind of trivial, given that set_attributes () can change owner_id,
+ size, etc.
*/
+ if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_EDIT))
+ {
+ return False;
+ }
+
+ if (!$this->file_exists ($file, array ($relatives[0])))
+ {
+ return False;
+ }
+
+ /*
+ All this voodoo just decides which attributes to keep, and which to update
+ depending on if the attribute was supplied in the $attributes array
+ */
+
+ $ls_array = $this->ls ($p->fake_full_path, array ($p->mask), False, False, True);
+ $record = $ls_array[0];
+
+ $attribute_names = array ("owner_id", "createdby_id", "modifiedby_id", "created", "modified", "size", "mime_type", "deleteable", "comment", "app", "link_directory", "link_name", "version");
+
+ while (list ($num, $attribute) = each ($attribute_names))
+ {
+ if (isset ($attributes[$attribute]))
+ {
+ $$attribute = $attributes[$attribute];
+
+ /*
+ Indicate that the EDITED_COMMENT operation needs to be journaled,
+ but only if the comment changed
+ */
+ if ($attribute == "comment" && $attributes[$attribute] != $record[$attribute])
+ {
+ $edited_comment = 1;
+ }
+ }
+ else
+ {
+ $$attribute = $record[$attribute];
+ }
+
+ $$attribute = $this->db_clean ($$attribute);
+ }
+
+ $sql = "UPDATE phpgw_vfs SET ";
+
+ reset ($attribute_names);
+ while (list ($num, $attribute) = each ($attribute_names))
+ {
+ if ($num)
+ {
+ $sql .= ", ";
+ }
+
+ $sql .= "$attribute='" . $$attribute . "'";
+ }
+
+ $sql .= " WHERE file_id='$record[file_id]'";
+ $sql .= $this->extra_sql (VFS_SQL_UPDATE);
+
+ $query = $phpgw->db->query ($sql, __LINE__, __FILE__);
+
+ if ($query)
+ {
+ if ($edited_comment)
+ {
+ $this->add_journal ($p->fake_full_path, array ($p->mask), VFS_OPERATION_EDITED_COMMENT);
+ }
+
+ return True;
+ }
+ else
+ {
+ return False;
+ }
}
-
- /*
- We don't use ls () because it calls file_type () to determine if it has been
- passed a directory
+
+ /*!
+ @function correct_attributes
+ @abstract Set the correct attributes for $string (e.g. owner)
+ @param $string File/directory to correct attributes of
+ @param $relatives Relativity array
+ @result Boolean True/False
*/
- $query = $phpgw->db->query ("SELECT mime_type FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'" . $this->extra_sql (VFS_SQL_SELECT), __LINE__, __FILE__);
- $phpgw->db->next_record ();
- $mime_type = $phpgw->db->Record["mime_type"];
-
- return ($mime_type);
- }
-
- /*!
- @function file_exists
- @abstract check if file/directory exists
- @param $string file/directory to check existance of
- @param $relatives Relativity array
- @result Boolean True/False
- */
-
- function file_exists ($string, $relatives = array (RELATIVE_CURRENT))
- {
- global $phpgw;
-
- $p = $this->path_parts ($string, array ($relatives[0]));
-
- if ($p->outside)
+
+ function correct_attributes ($string, $relatives = array (RELATIVE_CURRENT))
{
- $rr = file_exists ($p->real_full_path);
-
- return $rr;
+ global $phpgw;
+
+ $p = $this->path_parts ($string, array ($relatives[0]));
+
+ if ($p->fake_leading_dirs != $this->fakebase && $p->fake_leading_dirs != "/")
+ {
+ $ls_array = $this->ls ($p->fake_leading_dirs, array ($p->mask), False, False, True);
+ $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("owner_id" => $ls_array[0]["owner_id"]));
+
+ return True;
+ }
+ elseif (preg_match ("+^$this->fakebase\/(.*)$+U", $p->fake_full_path, $matches))
+ {
+ $this->set_attributes ($p->fake_full_path, array ($p->mask), array ("owner_id" => $phpgw->accounts->name2id ($matches[1])));
+
+ return True;
+ }
+ else
+ {
+ $this->set_attributes ($p->fake_full_name, array ($p->mask), array ("owner_id" => 0));
+
+ return True;
+ }
}
-
- $query = $phpgw->db->query ("SELECT name FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'" . $this->extra_sql (VFS_SQL_SELECT), __LINE__, __FILE__);
-
- if ($phpgw->db->next_record ())
- {
- return True;
- }
- else
- {
- return False;
- }
- }
-
- /*!
- @function get_size
- @abstract Return size of $string
- @param $string file/directory to get size of
- @param $relatives Relativity array
- @param $checksubdirs Boolean, recursively add the size of all sub directories as well?
- @result Size of $string in bytes
- */
-
- function get_size ($string, $relatives = array (RELATIVE_CURRENT), $checksubdirs = True)
- {
- global $phpgw, $phpgw_info;
-
- $p = $this->path_parts ($string, array ($relatives[0]));
-
- if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_READ, True))
- {
- return False;
- }
-
- /*
- WIP - this should run through all of the subfiles/directories in the directory and tally up
- their sizes. Should modify ls () to be able to return a list for files outside the virtual root
+
+ /*!
+ @function file_type
+ @abstract return file/dir type (MIME or other)
+ @param $file File or directory path (/home/user/dir/dir2/dir3, /home/user/dir/dir2/file)
+ @param $relatives Relativity array
+ @result MIME type, "Directory", or nothing if MIME type is not known
*/
- if ($p->outside)
+
+ function file_type ($file, $relatives = array (RELATIVE_CURRENT))
{
- $size = filesize ($p->real_full_path);
-
+ global $phpgw;
+
+ $p = $this->path_parts ($file, array ($relatives[0]));
+
+ if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_READ, True))
+ {
+ return False;
+ }
+
+ if ($p->outside)
+ {
+ if (is_dir ($p->real_full_path))
+ {
+ return ("Directory");
+ }
+
+ /*
+ We don't return an empty string here, because it may still match with a database query
+ because of linked directories
+ */
+ }
+
+ /*
+ We don't use ls () because it calls file_type () to determine if it has been
+ passed a directory
+ */
+ $query = $phpgw->db->query ("SELECT mime_type FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'" . $this->extra_sql (VFS_SQL_SELECT), __LINE__, __FILE__);
+ $phpgw->db->next_record ();
+ $mime_type = $phpgw->db->Record["mime_type"];
+
+ return ($mime_type);
+ }
+
+ /*!
+ @function file_exists
+ @abstract check if file/directory exists
+ @param $string file/directory to check existance of
+ @param $relatives Relativity array
+ @result Boolean True/False
+ */
+
+ function file_exists ($string, $relatives = array (RELATIVE_CURRENT))
+ {
+ global $phpgw;
+
+ $p = $this->path_parts ($string, array ($relatives[0]));
+
+ if ($p->outside)
+ {
+ $rr = file_exists ($p->real_full_path);
+
+ return $rr;
+ }
+
+ $query = $phpgw->db->query ("SELECT name FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'" . $this->extra_sql (VFS_SQL_SELECT), __LINE__, __FILE__);
+
+ if ($phpgw->db->next_record ())
+ {
+ return True;
+ }
+ else
+ {
+ return False;
+ }
+ }
+
+ /*!
+ @function get_size
+ @abstract Return size of $string
+ @param $string file/directory to get size of
+ @param $relatives Relativity array
+ @param $checksubdirs Boolean, recursively add the size of all sub directories as well?
+ @result Size of $string in bytes
+ */
+
+ function get_size ($string, $relatives = array (RELATIVE_CURRENT), $checksubdirs = True)
+ {
+ global $phpgw, $phpgw_info;
+
+ $p = $this->path_parts ($string, array ($relatives[0]));
+
+ if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_READ, True))
+ {
+ return False;
+ }
+
+ /*
+ WIP - this should run through all of the subfiles/directories in the directory and tally up
+ their sizes. Should modify ls () to be able to return a list for files outside the virtual root
+ */
+ if ($p->outside)
+ {
+ $size = filesize ($p->real_full_path);
+
+ return $size;
+ }
+
+ $ls_array = $this->ls ($p->fake_full_path, array ($p->mask), $checksubdirs, False, !$checksubdirs);
+
+ while (list ($num, $file_array) = each ($ls_array))
+ {
+ /*
+ Make sure the file is in the directory we want, and not
+ some deeper nested directory with a similar name
+ */
+ if (!ereg ("^$p->fake_full_path", $file_array["directory"]))
+ {
+ continue;
+ }
+
+ $size += $file_array["size"];
+ }
+
+ if ($checksubdirs)
+ {
+ $query = $phpgw->db->query ("SELECT size FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'" . $this->extra_sql (VFS_SQL_SELECT));
+ $phpgw->db->next_record ();
+ $size += $phpgw->db->Record[0];
+ }
+
return $size;
}
-
- $ls_array = $this->ls ($p->fake_full_path, array ($p->mask), $checksubdirs, False, !$checksubdirs);
-
- while (list ($num, $file_array) = each ($ls_array))
+
+ /*!
+ @function checkperms
+ @abstract Check if $this->working_id has write access to create files in $dir
+ @discussion Simple call to acl_check
+ @param $dir Directory to check access of
+ @param $relatives Relativity array
+ @result Boolean True/False
+ */
+
+ function checkperms ($dir, $relatives = array (RELATIVE_CURRENT))
{
- /*
- Make sure the file is in the directory we want, and not
- some deeper nested directory with a similar name
- */
- if (!ereg ("^$p->fake_full_path", $file_array["directory"]))
+ global $phpgw, $phpgw_info;
+
+ $p = $this->path_parts ($dir, array ($relatives[0]));
+
+ if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_ADD))
{
- continue;
+ return False;
+ }
+ else
+ {
+ return True;
}
-
- $size += $file_array["size"];
}
-
- if ($checksubdirs)
+
+ /*!
+ @function ls
+ @abstract get directory listing or info about a single file
+ @discussion Note: The entries are not guaranteed to be returned in any logical order
+ Note: The size for directories does not include subfiles/subdirectories.
+ If you need that, use $this->get_size ()
+ @param $dir File or Directory
+ @param $relatives Relativity array
+ @param $checksubdirs Boolean, recursively list all sub directories as well?
+ @param $mime_type Only return entries matching MIME-type $mime_type. Can be any MIME-type, "Directory" or "\ " for those without MIME types
+ @param $nofiles Boolean. True means you want to return just the information about the directory $dir. If $dir is a file, $nofiles is implied. This is the equivalent of 'ls -ld $dir'
+ @param $orderby How to order results. Note that this only works for directories inside the virtual root
+ @result array of arrays. Subarrays contain full info for each file/dir.
+ */
+
+ function ls ($dir = False, $relatives = array (RELATIVE_CURRENT), $checksubdirs = True, $mime_type = False, $nofiles = False, $orderby = "directory")
{
- $query = $phpgw->db->query ("SELECT size FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'" . $this->extra_sql (VFS_SQL_SELECT));
- $phpgw->db->next_record ();
- $size += $phpgw->db->Record[0];
- }
-
- return $size;
- }
-
- /*!
- @function checkperms
- @abstract Check if $this->working_id has write access to create files in $dir
- @discussion Simple call to acl_check
- @param $dir Directory to check access of
- @param $relatives Relativity array
- @result Boolean True/False
- */
-
- function checkperms ($dir, $relatives = array (RELATIVE_CURRENT))
- {
- global $phpgw, $phpgw_info;
-
- $p = $this->path_parts ($dir, array ($relatives[0]));
-
- if (!$this->acl_check ($p->fake_full_path, array ($p->mask), PHPGW_ACL_ADD))
- {
- return False;
- }
- else
- {
- return True;
- }
- }
-
- /*!
- @function ls
- @abstract get directory listing or info about a single file
- @discussion Note: The entries are not guaranteed to be returned in any logical order
- Note: The size for directories does not include subfiles/subdirectories.
- If you need that, use $this->get_size ()
- @param $dir File or Directory
- @param $relatives Relativity array
- @param $checksubdirs Boolean, recursively list all sub directories as well?
- @param $mime_type Only return entries matching MIME-type $mime_type. Can be any MIME-type, "Directory" or "\ " for those without MIME types
- @param $nofiles Boolean. True means you want to return just the information about the directory $dir. If $dir is a file, $nofiles is implied. This is the equivalent of 'ls -ld $dir'
- @param $orderby How to order results. Note that this only works for directories inside the virtual root
- @result array of arrays. Subarrays contain full info for each file/dir.
- */
-
- function ls ($dir = False, $relatives = array (RELATIVE_CURRENT), $checksubdirs = True, $mime_type = False, $nofiles = False, $orderby = "directory")
- {
- global $phpgw, $phpgw_info;
-
- $p = $this->path_parts ($dir, array ($relatives[0]));
- $dir = $p->fake_full_path;
-
- /* If they pass us a file or $nofiles is set, return the info for $dir only */
- if (((($type = $this->file_type ($dir, array ($p->mask))) != "Directory") || ($nofiles)) && !$p->outside)
- {
- /* SELECT all, the, attributes */
+ global $phpgw, $phpgw_info;
+
+ $p = $this->path_parts ($dir, array ($relatives[0]));
+ $dir = $p->fake_full_path;
+
+ /* If they pass us a file or $nofiles is set, return the info for $dir only */
+ if (((($type = $this->file_type ($dir, array ($p->mask))) != "Directory") || ($nofiles)) && !$p->outside)
+ {
+ /* SELECT all, the, attributes */
+ $sql = "SELECT ";
+
+ reset ($this->attributes);
+ while (list ($num, $attribute) = each ($this->attributes))
+ {
+ if ($num)
+ {
+ $sql .= ", ";
+ }
+
+ $sql .= "$attribute";
+ }
+
+ $sql .= " FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'";
+
+ $sql .= $this->extra_sql (VFS_SQL_SELECT);
+
+ $query = $phpgw->db->query ($sql, __LINE__, __FILE__);
+
+ $phpgw->db->next_record ();
+ $record = $phpgw->db->Record;
+
+ /* We return an array of one array to maintain the standard */
+ $rarray = array ();
+ reset ($this->attributes);
+ while (list ($num, $attribute) = each ($this->attributes))
+ {
+ $rarray[0][$attribute] = $record[$attribute];
+ }
+
+ return $rarray;
+ }
+
+ //WIP - this should recurse using the same options the virtual part of ls () does
+ /* If $dir is outside the virutal root, we have to check the file system manually */
+ if ($p->outside)
+ {
+ if ($this->file_type ($p->fake_full_path, array ($p->mask)) == "Directory" && !$nofiles)
+ {
+ $dir_handle = opendir ($p->real_full_path);
+ while ($filename = readdir ($dir_handle))
+ {
+ if ($filename == "." || $filename == "..")
+ {
+ continue;
+ }
+
+ $rarray[] = $this->get_real_info ($p->real_full_path . SEP . $filename, array ($p->mask));
+ }
+ }
+ else
+ {
+ $rarray[] = $this->get_real_info ($p->real_full_path, array ($p->mask));
+ }
+
+ return $rarray;
+ }
+
+ /* $dir's not a file, is inside the virtual root, and they want to check subdirs */
+ /* SELECT all, the, attributes FROM phpgw_vfs WHERE file=$dir */
$sql = "SELECT ";
-
+
reset ($this->attributes);
while (list ($num, $attribute) = each ($this->attributes))
{
if ($num)
+ {
$sql .= ", ";
-
+ }
+
$sql .= "$attribute";
}
-
- $sql .= " FROM phpgw_vfs WHERE directory='$p->fake_leading_dirs_clean' AND name='$p->fake_name_clean'";
-
+
+ $dir_clean = $this->db_clean ($dir);
+ $sql .= " FROM phpgw_vfs WHERE directory LIKE '$dir_clean%'";
$sql .= $this->extra_sql (VFS_SQL_SELECT);
-
+
+ if ($mime_type)
+ {
+ $sql .= " AND mime_type='$mime_type'";
+ }
+
+ $sql .= " ORDER BY $orderby";
+
$query = $phpgw->db->query ($sql, __LINE__, __FILE__);
-
- $phpgw->db->next_record ();
- $record = $phpgw->db->Record;
-
- /* We return an array of one array to maintain the standard */
+
$rarray = array ();
- reset ($this->attributes);
- while (list ($num, $attribute) = each ($this->attributes))
+ for ($i = 0; $phpgw->db->next_record (); $i++)
{
- $rarray[0][$attribute] = $record[$attribute];
- }
-
- return $rarray;
- }
-
- //WIP - this should recurse using the same options the virtual part of ls () does
- /* If $dir is outside the virutal root, we have to check the file system manually */
- if ($p->outside)
- {
- if ($this->file_type ($p->fake_full_path, array ($p->mask)) == "Directory" && !$nofiles)
- {
- $dir_handle = opendir ($p->real_full_path);
- while ($filename = readdir ($dir_handle))
+ $record = $phpgw->db->Record;
+
+ /* Further checking on the directory. This makes sure /home/user/test won't match /home/user/test22 */
+ if (!ereg ("^$dir(/|$)", $record["directory"]))
{
- if ($filename == "." || $filename == "..")
- {
- continue;
- }
-
- $rarray[] = $this->get_real_info ($p->real_full_path . SEP . $filename, array ($p->mask));
+ continue;
+ }
+
+ /* If they want only this directory, then $dir should end without a trailing / */
+ if (!$checksubdirs && ereg ("^$dir/", $record["directory"]))
+ {
+ continue;
+ }
+
+ reset ($this->attributes);
+ while (list ($num, $attribute) = each ($this->attributes))
+ {
+ $rarray[$i][$attribute] = $record[$attribute];
}
}
- else
- {
- $rarray[] = $this->get_real_info ($p->real_full_path, array ($p->mask));
- }
-
+
return $rarray;
}
-
- /* $dir's not a file, is inside the virtual root, and they want to check subdirs */
- /* SELECT all, the, attributes FROM phpgw_vfs WHERE file=$dir */
- $sql = "SELECT ";
-
- reset ($this->attributes);
- while (list ($num, $attribute) = each ($this->attributes))
+
+ /*!
+ @function dir
+ @abstract shortcut to ls
+ */
+
+ function dir ($dir = False, $relatives = array (RELATIVE_CURRENT), $checksubdirs = True, $mime_type = False, $nofiles = False, $orderby = "directory")
{
- if ($num)
- $sql .= ", ";
-
- $sql .= "$attribute";
+ return $this->ls ($dir, $relatives, $checksubdirs, $mime_type, $nofiles, $orderby);
}
-
- $dir_clean = $this->db_clean ($dir);
- $sql .= " FROM phpgw_vfs WHERE directory LIKE '$dir_clean%'";
- $sql .= $this->extra_sql (VFS_SQL_SELECT);
-
- if ($mime_type)
+
+ /*!
+ @function update_real
+ @abstract Update database information for file or directory $string
+ @param $string File or directory to update database information for
+ @param $relatives Relativity array
+ @result Boolean True/False
+ */
+
+ function update_real ($string, $relatives = array (RELATIVE_CURRENT))
{
- $sql .= " AND mime_type='$mime_type'";
- }
-
- $sql .= " ORDER BY $orderby";
-
- $query = $phpgw->db->query ($sql, __LINE__, __FILE__);
-
- $rarray = array ();
- for ($i = 0; $phpgw->db->next_record (); $i++)
- {
- $record = $phpgw->db->Record;
-
- /* Further checking on the directory. This makes sure /home/user/test won't match /home/user/test22 */
- if (!ereg ("^$dir(/|$)", $record["directory"]))
+ global $phpgw, $phpgw_info;
+
+ $p = $this->path_parts ($string, array ($relatives[0]));
+
+ if (file_exists ($p->real_full_path))
{
- continue;
- }
-
- /* If they want only this directory, then $dir should end without a trailing / */
- if (!$checksubdirs && ereg ("^$dir/", $record["directory"]))
- {
- continue;
- }
-
- reset ($this->attributes);
- while (list ($num, $attribute) = each ($this->attributes))
- {
- $rarray[$i][$attribute] = $record[$attribute];
- }
- }
-
- return $rarray;
- }
-
- /*!
- @function dir
- @abstract shortcut to ls
- */
-
- function dir ($dir = False, $relatives = array (RELATIVE_CURRENT), $checksubdirs = True, $mime_type = False, $nofiles = False, $orderby = "directory")
- {
- return $this->ls ($dir, $relatives, $checksubdirs, $mime_type, $nofiles, $orderby);
- }
-
- /*!
- @function update_real
- @abstract Update database information for file or directory $string
- @param $string File or directory to update database information for
- @param $relatives Relativity array
- @result Boolean True/False
- */
-
- function update_real ($string, $relatives = array (RELATIVE_CURRENT))
- {
- global $phpgw, $phpgw_info;
-
- $p = $this->path_parts ($string, array ($relatives[0]));
-
- if (file_exists ($p->real_full_path))
- {
- if (is_dir ($p->real_full_path))
- {
- $dir_handle = opendir ($p->real_full_path);
- while ($filename = readdir ($dir_handle))
+ if (is_dir ($p->real_full_path))
{
- if ($filename == "." || $filename == "..")
+ $dir_handle = opendir ($p->real_full_path);
+ while ($filename = readdir ($dir_handle))
{
- continue;
+ if ($filename == "." || $filename == "..")
+ {
+ continue;
+ }
+
+ $rarray[] = $this->get_real_info ($p->fake_full_path . "/" . $filename, array (RELATIVE_NONE));
}
-
- $rarray[] = $this->get_real_info ($p->fake_full_path . "/" . $filename, array (RELATIVE_NONE));
- }
- }
- else
- {
- $rarray[] = $this->get_real_info ($p->fake_full_path, array (RELATIVE_NONE));
- }
-
- while (list ($num, $file_array) = each ($rarray))
- {
- $p2 = $this->path_parts ($file_array["directory"] . "/" . $file_array["name"], array (RELATIVE_NONE));
-
- /* Note the mime_type. This can be "Directory", which is how we create directories */
- $set_attributes_array = array ("size" => $file_array["size"], "mime_type" => $file_array["mime_type"]);
-
- if (!$this->file_exists ($p2->fake_full_path, array (RELATIVE_NONE)))
- {
- $this->touch ($p2->fake_full_path, array (RELATIVE_NONE));
-
- $this->set_attributes ($p2->fake_full_path, array (RELATIVE_NONE), $set_attributes_array);
}
else
{
- $this->set_attributes ($p2->fake_full_path, array (RELATIVE_NONE), $set_attributes_array);
+ $rarray[] = $this->get_real_info ($p->fake_full_path, array (RELATIVE_NONE));
+ }
+
+ while (list ($num, $file_array) = each ($rarray))
+ {
+ $p2 = $this->path_parts ($file_array["directory"] . "/" . $file_array["name"], array (RELATIVE_NONE));
+
+ /* Note the mime_type. This can be "Directory", which is how we create directories */
+ $set_attributes_array = array ("size" => $file_array["size"], "mime_type" => $file_array["mime_type"]);
+
+ if (!$this->file_exists ($p2->fake_full_path, array (RELATIVE_NONE)))
+ {
+ $this->touch ($p2->fake_full_path, array (RELATIVE_NONE));
+
+ $this->set_attributes ($p2->fake_full_path, array (RELATIVE_NONE), $set_attributes_array);
+ }
+ else
+ {
+ $this->set_attributes ($p2->fake_full_path, array (RELATIVE_NONE), $set_attributes_array);
+ }
}
}
}
- }
-
-
- /* Helper functions */
-
- /* This fetchs all available file system information for $string (not using the database) */
- function get_real_info ($string, $relatives = array (RELATIVE_CURRENT))
- {
- global $phpgw, $phpgw_info;
-
- $p = $this->path_parts ($string, array ($relatives[0]));
-
- if (is_dir ($p->real_full_path))
+
+
+ /* Helper functions */
+
+ /* This fetchs all available file system information for $string (not using the database) */
+ function get_real_info ($string, $relatives = array (RELATIVE_CURRENT))
{
- $mime_type = "Directory";
+ global $phpgw, $phpgw_info;
+
+ $p = $this->path_parts ($string, array ($relatives[0]));
+
+ if (is_dir ($p->real_full_path))
+ {
+ $mime_type = "Directory";
+ }
+
+ $size = filesize ($p->real_full_path);
+
+ $rarray = array ("directory" => $p->fake_leading_dirs, "name" => $p->fake_name, "size" => $size, "mime_type" => $mime_type);
+
+ return ($rarray);
}
-
- $size = filesize ($p->real_full_path);
-
- $rarray = array ("directory" => $p->fake_leading_dirs, "name" => $p->fake_name, "size" => $size, "mime_type" => $mime_type);
-
- return ($rarray);
}
-}
-
-?>
+
+ ?>