mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-14 20:14:11 +01:00
3924 lines
96 KiB
PHP
3924 lines
96 KiB
PHP
<?php
|
|
/**************************************************************************\
|
|
* eGroupWare API - VFS *
|
|
* This file written by Vinicius Cubas Brand, strongly based on vfs_sql of *
|
|
* Jason Wies (Zone) <zone@phpgroupware.org> *
|
|
* This class handles file/dir access for eGroupWare *
|
|
* Copyright (C) 2001 Jason Wies, (C) 2004 Vinicius Cubas Brand *
|
|
* and (c) 2006 Benjamin Donnachie *
|
|
* -------------------------------------------------------------------------*
|
|
* This library is part of the eGroupWare API *
|
|
* http://www.egroupware.org/api *
|
|
* ------------------------------------------------------------------------ *
|
|
* This library is free software; you can redistribute it and/or modify it *
|
|
* under the terms of the GNU Lesser General Public License as published by *
|
|
* the Free Software Foundation; either version 2.1 of the License, *
|
|
* or any later version. *
|
|
* This library is distributed in the hope that it will be useful, but *
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
* See the GNU Lesser General Public License for more details. *
|
|
* You should have received a copy of the GNU Lesser General Public License *
|
|
* along with this library; if not, write to the Free Software Foundation, *
|
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
|
|
\**************************************************************************/
|
|
|
|
/*!
|
|
@class vfs
|
|
@abstract Virtual File System with SQL backend - version 2
|
|
@description Authors: Zone, viniciuscb
|
|
*/
|
|
|
|
# viniciuscb 2004-09-06 Upgraded this class to the sql implementation v2.
|
|
|
|
/* These are used in calls to extra_sql () */
|
|
define ('DEFAULT_LOW_PERMS',0600);
|
|
|
|
#upd viniciuscb 2004-09-06 Updated to the new database tables (the ones that
|
|
# match phpgw_vfs2*). I have created a class to handle mime types and one
|
|
# to handle the versioning system.
|
|
|
|
#upd viniciuscb 2005-03-11 Deleted some garbage
|
|
|
|
#upd Benjamin Donnachie <benjamin@pythagoras.no-ip.org> 2006-01-09
|
|
# Fixed function in_docroot so that it works with asyncservices
|
|
|
|
/**
|
|
* Class: vfs
|
|
*
|
|
* Virtual File System class - SQL v.2 implementation
|
|
*/
|
|
class vfs extends vfs_shared
|
|
{
|
|
var $working_id;
|
|
var $working_lid;
|
|
var $meta_types;
|
|
var $now;
|
|
var $file_actions;
|
|
var $vfs_mimetypes;
|
|
var $vfs_versionsystem;
|
|
var $vfs_customfields;
|
|
var $vfs_sharing;
|
|
var $db;
|
|
var $db_hl;
|
|
var $appfiles_root;
|
|
|
|
var $Debug;
|
|
|
|
//other attributes may be in the custom fields....
|
|
|
|
var $attribute_tables = array(
|
|
'file_id' => 'phpgw_vfs2_files',
|
|
'owner_id' => 'phpgw_vfs2_files',
|
|
'createdby_id' => 'phpgw_vfs2_files',
|
|
'modifiedby_id' => 'phpgw_vfs2_files',
|
|
'created' => 'phpgw_vfs2_files',
|
|
'modified' => 'phpgw_vfs2_files',
|
|
'size' => 'phpgw_vfs2_files',
|
|
'mime_type' => 'phpgw_vfs2_mimetypes',
|
|
'comment' => 'phpgw_vfs2_files',
|
|
'app' => 'phpgw_vfs2_files',
|
|
'directory' => 'phpgw_vfs2_files',
|
|
'name' => 'phpgw_vfs2_files',
|
|
'link_directory'=> 'phpgw_vfs2_files',
|
|
'link_name' => 'phpgw_vfs2_files',
|
|
'version' => 'phpgw_vfs2_files'
|
|
);
|
|
|
|
//to external use.
|
|
//if $custom_field_support is set, then this class have support to
|
|
//custom fields.
|
|
var $custom_field_support = 1;
|
|
|
|
//if $search_support is set, then this class have support to
|
|
//searching in files for a particular value in a particular property.
|
|
var $search_support = 1;
|
|
|
|
var $compress_support = 1;
|
|
var $extract_support = 1;
|
|
|
|
|
|
/*!
|
|
@function vfs
|
|
@abstract constructor, sets up variables
|
|
*/
|
|
function vfs ()
|
|
{
|
|
|
|
//just in case... this must change soon.
|
|
if (@$GLOBALS['phpgw_info']['flags']['currentapp']=='filemanager')
|
|
{
|
|
echo "FILEMANAGER UNTESTED WITH VFS2. ABORTED.";
|
|
$GLOBALS['phpgw']->common->phpgw_exit();
|
|
}
|
|
|
|
$this->db = clone($GLOBALS['phpgw']->db);
|
|
$this->db_hl =& $GLOBALS['phpgw']->db_hl;
|
|
|
|
$this->vfs_shared ();
|
|
$this->basedir = $GLOBALS['phpgw_info']['server']['files_dir'];
|
|
$this->working_id = $GLOBALS['phpgw_info']['user']['account_id'];
|
|
$this->working_lid = $GLOBALS['phpgw']->accounts->id2name($this->working_id);
|
|
$this->now = date ('Y-m-d H:i:s');
|
|
|
|
|
|
/*
|
|
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 ()
|
|
|
|
set_attributes now uses this array(). 07-Dec-01 skeeter
|
|
*/
|
|
|
|
$this->attributes[] = 'deleteable';
|
|
$this->attributes[] = 'content';
|
|
$this->attributes[] = 'is_backup';
|
|
$this->attributes[] = 'shared';
|
|
$this->attributes[] = 'proper_id';
|
|
|
|
$this->attribute_tables['deleteable'] = 'phpgw_vfs2_files';
|
|
$this->attribute_tables['content'] = 'phpgw_vfs2_files';
|
|
$this->attribute_tables['is_backup'] = 'phpgw_vfs2_files';
|
|
$this->attribute_tables['shared'] = 'phpgw_vfs2_files';
|
|
$this->attribute_tables['proper_id'] = 'phpgw_vfs2_files';
|
|
|
|
/*
|
|
Decide whether to use any actual filesystem calls (fopen(),
|
|
fread(), unlink(), rmdir(), touch(), etc.). If not, then we're
|
|
working completely in the database.
|
|
*/
|
|
$this->file_actions = $GLOBALS['phpgw_info']['server']['file_store_contents'] == 'filesystem' ||
|
|
!$GLOBALS['phpgw_info']['server']['file_store_contents'];
|
|
|
|
// test if the files-dir is inside the document-root, and refuse
|
|
// working if so
|
|
if ($this->file_actions && $this->in_docroot($this->basedir))
|
|
{
|
|
$GLOBALS['phpgw']->common->phpgw_header();
|
|
if ($GLOBALS['phpgw_info']['flags']['noheader'])
|
|
{
|
|
echo parse_navbar();
|
|
}
|
|
echo '<p align="center"><font color="red"><b>'.lang('Path to user and group files HAS TO BE OUTSIDE of the webservers document-root!!!')."</b></font></p>\n";
|
|
$GLOBALS['phpgw']->common->phpgw_exit();
|
|
}
|
|
|
|
/* We store the linked directories in an array now, so we don't
|
|
* have to make the SQL call again */
|
|
|
|
|
|
|
|
|
|
$this->linked_dirs = array ();
|
|
while ($GLOBALS['phpgw']->db->next_record ())
|
|
{
|
|
$this->linked_dirs[] = $GLOBALS['phpgw']->db->Record;
|
|
}
|
|
|
|
//set_vfs to use this very object (pass by reference)
|
|
$this->vfs_mimetypes =& CreateObject('phpgwapi.vfs_mimetypes',false);
|
|
$this->vfs_mimetypes->set_vfs($this);
|
|
|
|
$this->vfs_versionsystem =& CreateObject('phpgwapi.vfs_versionsystem',false);
|
|
$this->vfs_versionsystem->set_vfs($this);
|
|
|
|
$this->vfs_customfields =& CreateObject('phpgwapi.vfs_customfields');
|
|
|
|
$this->vfs_sharing =& CreateObject('phpgwapi.vfs_sharing');
|
|
}
|
|
|
|
/*!
|
|
@function in_docroot
|
|
@abstract test if $path lies within the webservers document-root
|
|
*/
|
|
function in_docroot($path)
|
|
{
|
|
$docroots = array(PHPGW_SERVER_ROOT,$_SERVER['DOCUMENT_ROOT']);
|
|
|
|
foreach ($docroots as $docroot)
|
|
{
|
|
$len = strlen($docroot);
|
|
|
|
if ($docroot != "" && $docroot == substr($path,0,$len))
|
|
{
|
|
$rest = substr($path,$len);
|
|
|
|
if (!strlen($rest) || $rest[0] == DIRECTORY_SEPARATOR)
|
|
{
|
|
return True;
|
|
}
|
|
}
|
|
}
|
|
return False;
|
|
}
|
|
|
|
/*!
|
|
@function get_id_from_path
|
|
@abstract Given a Directory and file name, finds the correspondent
|
|
file_id
|
|
@param $directory string
|
|
@param $name string
|
|
@result int the file_id in repository
|
|
*/
|
|
function get_id_from_path($directory,$name)
|
|
{
|
|
$where = array(
|
|
'directory' => $directory,
|
|
'name' => $name
|
|
);
|
|
|
|
$this->db->select('phpgw_vfs2_files','file_id',$where,
|
|
__LINE__,__FILE__);
|
|
|
|
if ($this->db->next_record())
|
|
{
|
|
return $this->db->Record['file_id'];
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//the inverse way of $this->get_id_from_path
|
|
function get_path_from_id($id)
|
|
{
|
|
$where = array(
|
|
'file_id' => $id
|
|
);
|
|
|
|
$this->db->select('phpgw_vfs2_files','directory,name',$where,
|
|
__LINE__,__FILE__);
|
|
|
|
if ($this->db->next_record())
|
|
{
|
|
return $this->db->Record['directory'].'/'.$this->db->Record['name'];
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
function get_journal ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT),
|
|
'type' => False
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
if (!$this->acl_check (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask)
|
|
)))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
//find the file_id from a file based on directory and name
|
|
$file_id = $this->get_id_from_path($p->fake_leading_dirs_clean,$p->fake_name_clean);
|
|
|
|
|
|
if ($file_id === false)
|
|
{
|
|
return false;
|
|
}
|
|
return $this->vfs_versionsystem->get_journal($file_id);
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
function acl_check ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT),
|
|
'operation' => PHPGW_ACL_READ,
|
|
'must_exist' => False
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
/* Accommodate special situations */
|
|
if ($this->override_acl || $data['relatives'][0] == RELATIVE_USER_APP || $GLOBALS['phpgw_info']['user']['apps']['admin'])
|
|
{
|
|
return True;
|
|
}
|
|
|
|
if (!$data['owner_id'])
|
|
{
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
/* Temporary, until we get symlink type files set up */
|
|
if ($p->outside)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
/* Read access is always allowed here, but nothing else is */
|
|
if ($data['string'] == '/' || $data['string'] == $this->fakebase)
|
|
{
|
|
if ($data['operation'] == PHPGW_ACL_READ)
|
|
{
|
|
return True;
|
|
}
|
|
else
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
|
|
/* If the file doesn't exist, we get ownership from the parent
|
|
* directory */
|
|
if (!$this->file_exists (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask)
|
|
))
|
|
)
|
|
{
|
|
if ($data['must_exist'])
|
|
{
|
|
return False;
|
|
}
|
|
|
|
$data['string'] = $p->fake_leading_dirs;
|
|
$p2 = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($p->mask)
|
|
)
|
|
);
|
|
|
|
if (!$this->file_exists (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($p->mask)
|
|
))
|
|
)
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$p2 = $p;
|
|
}
|
|
/*
|
|
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 = $GLOBALS['phpgw']->db->query ("SELECT owner_id FROM phpgw_vfs2_files WHERE directory='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p2->fake_leading_dirs_clean)."' AND name='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p2->fake_name_clean)."'", __LINE__, __FILE__);
|
|
$GLOBALS['phpgw']->db->next_record ();
|
|
|
|
$owner_id = $GLOBALS['phpgw']->db->Record['owner_id'];
|
|
}
|
|
else
|
|
{
|
|
$owner_id = $data['owner_id'];
|
|
}
|
|
|
|
/* This is correct. The ACL currently doesn't handle undefined values correctly */
|
|
if (!$owner_id)
|
|
{
|
|
$owner_id = 0;
|
|
}
|
|
|
|
$user_id = $GLOBALS['phpgw_info']['user']['account_id'];
|
|
|
|
/* They always have access to their own files */
|
|
if ($owner_id == $user_id)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
|
|
#viniciuscb: Check if the file is inside a dir which is an application dir.
|
|
# If so, see if the dir has permissions in vfs_sharing. If not,
|
|
# inherit permissions given by the source application
|
|
|
|
if ($this->is_appfolder($p2->fake_full_path))
|
|
{
|
|
$file_id = $this->get_file_id(array(
|
|
'string' => $p2->fake_full_path,
|
|
'relatives' => array($p2->mask)));
|
|
|
|
$rights = $this->vfs_sharing->get_file_permissions($GLOBALS['phpgw_info']['user']['account_id'],$file_id);
|
|
|
|
if ($rights & $data['operation'])
|
|
{
|
|
return true;
|
|
}
|
|
|
|
$exp_path = explode('/',$p2->fake_full_path);
|
|
$appname = $exp_path[2];
|
|
$id = $exp_path[3];
|
|
|
|
//get hooks to know node permission
|
|
$resp = $GLOBALS['phpgw']->hooks->process(array(
|
|
'location' => 'files_info',
|
|
'account_id' => $GLOBALS['phpgw_info']['user']['account_id']
|
|
));
|
|
|
|
return ($resp[$appname][$id]['permissions'] & $data['operation']);
|
|
}
|
|
|
|
#viniciuscb: rethink the group files role and working schema
|
|
/* Check if they're in the group */
|
|
$memberships = $GLOBALS['phpgw']->accounts->membership ($user_id);
|
|
|
|
if (is_array ($memberships))
|
|
{
|
|
foreach ($memberships as $group_array)
|
|
{
|
|
if ($owner_id == $group_array['account_id'])
|
|
{
|
|
$group_ok = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
$acl = CreateObject ('phpgwapi.acl', $owner_id);
|
|
$acl->account_id = $owner_id;
|
|
$acl->read_repository ();
|
|
|
|
$file_id = $this->get_file_id(array(
|
|
'string' => $p2->fake_full_path,
|
|
'relatives' => array($p2->mask)));
|
|
|
|
$rights = $this->vfs_sharing->get_file_permissions($user_id,$file_id);
|
|
|
|
if ($this->Debug)
|
|
{
|
|
echo "<br>\nRIGHTS OF THE FILE ".$p2->fake_full_path." ARE=$rights<br>\n";
|
|
}
|
|
|
|
if ($rights & $data['operation'])
|
|
{
|
|
return True;
|
|
}
|
|
elseif (!$rights && $group_ok)
|
|
{
|
|
$conf =& CreateObject('phpgwapi.config', 'phpgwapi');
|
|
$conf->read_repository();
|
|
if ($conf->config_data['acl_default'] == 'grant')
|
|
{
|
|
return True;
|
|
}
|
|
else
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
function read ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT)
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
if (!$this->acl_check (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'operation' => PHPGW_ACL_READ
|
|
))
|
|
)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
$conf =& CreateObject('phpgwapi.config', 'phpgwapi');
|
|
$conf->read_repository();
|
|
if ($this->file_actions || $p->outside)
|
|
{
|
|
if ($fp = fopen ($p->real_full_path, 'rb'))
|
|
{
|
|
$contents = fread ($fp, filesize ($p->real_full_path));
|
|
fclose ($fp);
|
|
}
|
|
else
|
|
{
|
|
$contents = False;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$ls_array = $this->ls (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
)
|
|
);
|
|
|
|
$contents = $ls_array[0]['content'];
|
|
}
|
|
|
|
return $contents;
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
function write ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT),
|
|
'content' => ''
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
if ($this->file_exists (array (
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask)
|
|
))
|
|
)
|
|
{
|
|
$acl_operation = PHPGW_ACL_EDIT;
|
|
$journal_operation = VFS_OPERATION_EDITED;
|
|
}
|
|
else
|
|
{
|
|
$acl_operation = PHPGW_ACL_ADD;
|
|
}
|
|
|
|
if (!$this->acl_check (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'operation' => $acl_operation
|
|
))
|
|
)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
umask(0177);
|
|
|
|
/*
|
|
* If 'string' doesn't exist, touch () creates both the file and
|
|
* the database entry If 'string' does exist, touch () sets the
|
|
* modification time and modified by
|
|
*/
|
|
$this->touch (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask)
|
|
)
|
|
);
|
|
|
|
$conf =& CreateObject('phpgwapi.config', 'phpgwapi');
|
|
$conf->read_repository();
|
|
|
|
|
|
$file_id = $this->get_id_from_path($p->fake_leading_dirs_clean,$p->fake_name_clean);
|
|
|
|
//Saves a snapshot in the journal
|
|
if ($journal_operation)
|
|
{
|
|
$this->vfs_versionsystem->save_snapshot($file_id,$journal_operation);
|
|
}
|
|
|
|
if ($this->file_actions)
|
|
{
|
|
if ($fp = fopen ($p->real_full_path, 'wb'))
|
|
{
|
|
fwrite ($fp, $data['content'], strlen ($data['content']));
|
|
fclose ($fp);
|
|
$write_ok = 1;
|
|
}
|
|
}
|
|
|
|
if ($write_ok || !$this->file_actions)
|
|
{
|
|
|
|
|
|
if ($this->file_actions)
|
|
{
|
|
$set_attributes_array = array(
|
|
'size' => filesize ($p->real_full_path)
|
|
);
|
|
}
|
|
else
|
|
{
|
|
$set_attributes_array = array (
|
|
'size' => strlen ($data['content']),
|
|
'content' => $data['content']
|
|
);
|
|
}
|
|
|
|
if ($journal_operation)
|
|
{
|
|
$this->vfs_versionsystem->commit($file_id);
|
|
}
|
|
|
|
|
|
|
|
$this->set_attributes (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'attributes' => $set_attributes_array
|
|
));
|
|
|
|
return True;
|
|
}
|
|
else
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
function touch ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array(
|
|
'relatives' => array (RELATIVE_CURRENT)
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$account_id = $GLOBALS['phpgw_info']['user']['account_id'];
|
|
$currentapp = $GLOBALS['phpgw_info']['flags']['currentapp'];
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
));
|
|
|
|
umask (0177);
|
|
|
|
if ($this->file_actions)
|
|
{
|
|
/*
|
|
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 (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask)
|
|
))
|
|
)
|
|
{
|
|
if (!$this->acl_check (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'operation' => PHPGW_ACL_EDIT
|
|
)))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
$vr = $this->set_attributes (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'attributes' => array(
|
|
'modifiedby_id' => $account_id,
|
|
'modified' => $this->now
|
|
)
|
|
)
|
|
);
|
|
}
|
|
else
|
|
{
|
|
if (!$this->acl_check (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'operation' => PHPGW_ACL_ADD
|
|
))
|
|
)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
//TODO VCB insert other fields
|
|
|
|
$insert_data = array(
|
|
'owner_id' => $this->working_id,
|
|
'directory' => $p->fake_leading_dirs_clean,
|
|
'name' => $p->fake_name_clean
|
|
);
|
|
|
|
$query = $this->db->insert('phpgw_vfs2_files',$insert_data,$insert_data,__LINE__,__FILE__);
|
|
|
|
$file_id = $this->get_id_from_path($p->fake_leading_dirs_clean,$p->fake_name_clean);
|
|
|
|
$this->vfs_versionsystem->create_initial_version($file_id);
|
|
|
|
$this->set_attributes(array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'attributes' => array (
|
|
'createdby_id' => $account_id,
|
|
'created' => $this->now,
|
|
'size' => 0,
|
|
'deleteable' => 'Y',
|
|
'app' => $currentapp
|
|
)
|
|
)
|
|
);
|
|
|
|
$this->correct_attributes (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask)
|
|
)
|
|
);
|
|
}
|
|
|
|
if ($rr || $vr || $query)
|
|
{
|
|
return True;
|
|
}
|
|
else
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
* If $data['symlink'] the file is symlinked instead of copied
|
|
*/
|
|
function cp ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT, RELATIVE_CURRENT),
|
|
'journal' => true
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$account_id = $GLOBALS['phpgw_info']['user']['account_id'];
|
|
|
|
$f = $this->path_parts (array(
|
|
'string' => $data['from'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
$t = $this->path_parts (array(
|
|
'string' => $data['to'],
|
|
'relatives' => array ($data['relatives'][1])
|
|
)
|
|
);
|
|
|
|
if (!$this->acl_check (array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => array ($f->mask),
|
|
'operation' => PHPGW_ACL_READ
|
|
))
|
|
)
|
|
{
|
|
trigger_error('vfs->cp: could not copy file from '.$f->fake_full_path.' to '.$t->fake_full_path.'. Without permission to read from source location. Line '.__LINE__.', File '.__FILE__,E_USER_NOTICE);
|
|
return False;
|
|
}
|
|
|
|
if ($exists = $this->file_exists (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask)
|
|
))
|
|
)
|
|
{
|
|
if (!$this->acl_check (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask),
|
|
'operation' => PHPGW_ACL_EDIT
|
|
))
|
|
)
|
|
{
|
|
trigger_error('vfs->cp: could not copy file from '.$f->fake_full_path.' to '.$t->fake_full_path.'. Without permission to edit destination. Line '.__LINE__.', File '.__FILE__,E_USER_NOTICE);
|
|
return False;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!$this->acl_check (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask),
|
|
'operation' => PHPGW_ACL_ADD
|
|
))
|
|
)
|
|
{
|
|
|
|
trigger_error('vfs->cp: could not copy file from '.$f->fake_full_path.' to '.$t->fake_full_path.'. Without permission to create new file. Line '.__LINE__.', File '.__FILE__,E_USER_NOTICE);
|
|
return False;
|
|
}
|
|
}
|
|
|
|
umask(0177);
|
|
|
|
if ($this->file_type (array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => array ($f->mask)
|
|
)) != 'Directory'
|
|
)
|
|
{
|
|
if ($this->file_actions)
|
|
{
|
|
if (@$data['symlink'])
|
|
{
|
|
if ($exists)
|
|
{
|
|
@unlink($t->real_full_path);
|
|
}
|
|
if (!symlink($f->real_full_path, $t->real_full_path))
|
|
{
|
|
trigger_error('vfs->cp: could not copy file from '.$f->fake_full_path.' to '.$t->fake_full_path.'. Without permission to create symbolic link. Line '.__LINE__.', File '.__FILE__,E_USER_NOTICE);
|
|
return False;
|
|
}
|
|
}
|
|
elseif (!copy ($f->real_full_path, $t->real_full_path))
|
|
{
|
|
trigger_error('vfs->cp: could not copy file from '.$f->fake_full_path.' to '.$t->fake_full_path.'. Line '.__LINE__.', File '.__FILE__,E_USER_NOTICE);
|
|
return False;
|
|
}
|
|
|
|
$size = filesize ($t->real_full_path);
|
|
}
|
|
else
|
|
{
|
|
$content = $this->read (array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => array ($f->mask)
|
|
)
|
|
);
|
|
|
|
|
|
$size = strlen ($content);
|
|
}
|
|
|
|
if ($t->outside)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
$ls_array = $this->ls (array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => array ($f->mask),
|
|
'checksubdirs' => False,
|
|
'mime_type' => False,
|
|
'nofiles' => True
|
|
)
|
|
);
|
|
$record = $ls_array[0];
|
|
|
|
if ($this->file_exists (array(
|
|
'string' => $data['to'],
|
|
'relatives' => array ($data['relatives'][1])
|
|
))
|
|
)
|
|
{ //Overwrite
|
|
|
|
/*
|
|
$query = $GLOBALS['phpgw']->db->query ("UPDATE phpgw_vfs SET owner_id='$this->working_id', directory='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($t->fake_leading_dirs_clean)."', name='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($t->fake_name_clean)."' WHERE owner_id='$this->working_id' AND directory='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($t->fake_leading_dirs_clean)."' AND name='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($t->fake_name_clean)."'", __LINE__, __FILE__);*/
|
|
|
|
$ls_array_dest = $this->ls (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask),
|
|
'checksubdirs' => False,
|
|
'mime_type' => False,
|
|
'nofiles' => True
|
|
)
|
|
);
|
|
$record_dest = $ls_array_dest[0];
|
|
|
|
$this->vfs_versionsystem->save_snapshot($record_dest['file_id'],VFS_OPERATION_EDITED,'Overwritten by copy of '.$f->fake_full_path_clean);
|
|
|
|
$set_attributes_array = array (
|
|
'createdby_id' => $account_id,
|
|
'created' => $this->now,
|
|
'size' => $size,
|
|
'mime_type' => $record['mime_type'],
|
|
'deleteable' => $record['deleteable'],
|
|
'comment' => $record['comment'],
|
|
'app' => $record['app']
|
|
);
|
|
|
|
if (!$this->file_actions)
|
|
{
|
|
$set_attributes_array['content'] = $content;
|
|
}
|
|
|
|
$res = $this->set_attributes(array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask),
|
|
'attributes' => $set_attributes_array
|
|
)
|
|
);
|
|
|
|
if ($res)
|
|
$this->vfs_versionsystem->commit($record_dest['file_id']);
|
|
}
|
|
else //Create a new file
|
|
{
|
|
$this->touch (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask)
|
|
)
|
|
);
|
|
|
|
$set_attributes_array = array (
|
|
'createdby_id' => $account_id,
|
|
'created' => $this->now,
|
|
'size' => $size,
|
|
'mime_type' => $record['mime_type'],
|
|
'deleteable' => $record['deleteable'],
|
|
'comment' => $record['comment'],
|
|
'app' => $record['app']
|
|
);
|
|
|
|
if (!$this->file_actions)
|
|
{
|
|
$set_attributes_array['content'] = $content;
|
|
}
|
|
|
|
$this->set_attributes(array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask),
|
|
'attributes' => $set_attributes_array
|
|
)
|
|
);
|
|
}
|
|
$this->correct_attributes (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask)
|
|
)
|
|
);
|
|
}
|
|
else /* It's a directory */
|
|
{
|
|
/* First, make the initial directory */
|
|
$this->mkdir (array(
|
|
'string' => $data['to'],
|
|
'relatives' => array ($data['relatives'][1])
|
|
)
|
|
);
|
|
|
|
/* Next, we create all the directories below the initial directory */
|
|
foreach($this->ls (array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => array ($f->mask),
|
|
'checksubdirs' => True,
|
|
'mime_type' => 'Directory'
|
|
)) as $entry)
|
|
{
|
|
$newdir = ereg_replace ("^$f->fake_full_path", "$t->fake_full_path", $entry['directory']);
|
|
$this->mkdir (array(
|
|
'string' => $newdir.'/'.$entry['name'],
|
|
'relatives' => array ($t->mask)
|
|
)
|
|
);
|
|
}
|
|
|
|
/* Lastly, we copy the files over */
|
|
foreach($this->ls (array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => array ($f->mask)
|
|
)) as $entry)
|
|
{
|
|
if ($entry['mime_type'] == 'Directory')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$newdir = ereg_replace ("^$f->fake_full_path", "$t->fake_full_path", $entry['directory']);
|
|
$this->cp (array(
|
|
'from' => "$entry[directory]/$entry[name]",
|
|
'to' => "$newdir/$entry[name]",
|
|
'relatives' => array ($f->mask, $t->mask)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
if (!$f->outside)
|
|
{
|
|
|
|
$ls_array = $this->ls(array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => $f->mask
|
|
));
|
|
|
|
$file = $ls_array[0];
|
|
|
|
$this->vfs_versionsystem->save_snapshot($file['file_id'],VFS_OPERATION_COPIED,'',array('dest' =>$t->fake_full_path));
|
|
|
|
$this->vfs_versionsystem->commit();
|
|
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
function mv ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT, RELATIVE_CURRENT)
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$account_id = $GLOBALS['phpgw_info']['user']['account_id'];
|
|
|
|
$f = $this->path_parts (array(
|
|
'string' => $data['from'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
$t = $this->path_parts (array(
|
|
'string' => $data['to'],
|
|
'relatives' => array ($data['relatives'][1])
|
|
)
|
|
);
|
|
|
|
if ($f->fake_full_path == $t->fake_full_path)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (!$this->acl_check (array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => array ($f->mask),
|
|
'operation' => PHPGW_ACL_READ
|
|
))
|
|
|| !$this->acl_check (array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => array ($f->mask),
|
|
'operation' => PHPGW_ACL_DELETE
|
|
))
|
|
)
|
|
{
|
|
trigger_error('vfs->mv: could not move file from '.$f->fake_full_path.' to '.$t->fake_full_path.'. Not allowed to delete the file from its source location. Line '.__LINE__.', File '.__FILE__,E_USER_NOTICE);
|
|
return False;
|
|
}
|
|
|
|
if (!$this->acl_check (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask),
|
|
'operation' => PHPGW_ACL_ADD
|
|
))
|
|
)
|
|
{
|
|
trigger_error('vfs->mv: could not move file from '.$f->fake_full_path.' to '.$t->fake_full_path.'. Not allowed to add a file in destination location. Line '.__LINE__.', File '.__FILE__,E_USER_NOTICE);
|
|
return False;
|
|
}
|
|
|
|
if ($this->file_exists (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask)
|
|
))
|
|
)
|
|
{
|
|
if (!$this->acl_check (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask),
|
|
'operation' => PHPGW_ACL_EDIT
|
|
))
|
|
)
|
|
{
|
|
trigger_error('vfs->mv: could not move file from '.$f->fake_full_path.' to '.$t->fake_full_path.'. Not allowed to edit existent file in destination location. Line '.__LINE__.', File '.__FILE__,E_USER_NOTICE);
|
|
return False;
|
|
}
|
|
}
|
|
|
|
umask (0177);
|
|
|
|
/* We can't move directories into themselves */
|
|
if (($this->file_type (array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => 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) == '/')
|
|
{
|
|
trigger_error('vfs->mv: could not move file from '.$f->fake_full_path.' to '.$t->fake_full_path.'. Trying to write in invalid location. Line '.__LINE__.', File '.__FILE__,E_USER_NOTICE);
|
|
return False;
|
|
}
|
|
}
|
|
|
|
if ($this->file_exists (array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => array ($f->mask)
|
|
))
|
|
)
|
|
{
|
|
|
|
/* We get the listing now, because it will change after we update the database */
|
|
$ls = $this->ls (array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => array ($f->mask)
|
|
)
|
|
);
|
|
|
|
//to the new version system.
|
|
$ls_fileonly = $this->ls(array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => array ($f->mask),
|
|
'checksudirs' => false,
|
|
'nofiles' => true
|
|
));
|
|
|
|
|
|
$this->vfs_versionsystem->save_snapshot(
|
|
$ls_fileonly[0]['file_id'],VFS_OPERATION_MOVED,
|
|
'Moved from '.$f->fake_full_path.' to '.$t->fake_full_path,
|
|
array('dest' => $t->fake_full_path));
|
|
|
|
if ($this->file_exists (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask)
|
|
))
|
|
)
|
|
{
|
|
$this->rm (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => 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)
|
|
{
|
|
//add_journal was here
|
|
}
|
|
|
|
/*
|
|
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 (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask)
|
|
)
|
|
);
|
|
|
|
$query = $GLOBALS['phpgw']->db->query ("UPDATE phpgw_vfs2_files SET size=$size WHERE directory='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($t->fake_leading_dirs_clean)."' AND name='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($t->fake_name_clean)."'", __LINE__, __FILE__);
|
|
}
|
|
elseif (!$t->outside)
|
|
{
|
|
|
|
$query = $GLOBALS['phpgw']->db->query ("UPDATE phpgw_vfs2_files SET name='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($t->fake_name_clean)."', directory='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($t->fake_leading_dirs_clean)."' WHERE directory='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($f->fake_leading_dirs_clean)."' AND name='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($f->fake_name_clean)."'", __LINE__, __FILE__);
|
|
}
|
|
|
|
|
|
/* $this->set_attributes(array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask),
|
|
'attributes' => array (
|
|
'modifiedby_id' => $account_id,
|
|
'modified' => $this->now
|
|
)
|
|
)
|
|
);*/
|
|
|
|
/* $this->correct_attributes (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask)
|
|
)
|
|
);*/
|
|
|
|
if ($this->file_actions)
|
|
{
|
|
if(file_exists($t->real_full_path))
|
|
{
|
|
unlink($t->real_full_path);
|
|
$ok = rename($f->real_full_path, $t->real_full_path);
|
|
}
|
|
else
|
|
{
|
|
$ok = rename($f->real_full_path, $t->real_full_path);
|
|
}
|
|
|
|
if (!$ok)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (is_dir($t->real_full_path) && $f->outside)
|
|
{
|
|
$this->update_real(array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => 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 (array(
|
|
'string' => $f->fake_full_path,
|
|
'relatives' => array($f->mask)
|
|
)
|
|
);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
trigger_error('vfs->mv: could not move file from '.$f->fake_full_path.' to '.$t->fake_full_path.'. Source file not found. Line '.__LINE__.', File '.__FILE__,E_USER_NOTICE);
|
|
return False;
|
|
}
|
|
|
|
if ($this->file_type (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask)
|
|
)) == 'Directory'
|
|
)
|
|
{
|
|
/* We got $ls from above, before we renamed the directory */
|
|
foreach ($ls as $entry)
|
|
{
|
|
$newdir = ereg_replace ("^$f->fake_full_path", $t->fake_full_path, $entry['directory']);
|
|
$newdir_clean = $this->clean_string (array ('string' => $newdir));
|
|
|
|
$query = $GLOBALS['phpgw']->db->query ("UPDATE phpgw_vfs2_files SET directory='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($newdir_clean)."' WHERE file_id='$entry[file_id]'",
|
|
__LINE__, __FILE__);
|
|
$this->correct_attributes (array(
|
|
'string' => "$newdir/$entry[name]",
|
|
'relatives' => array ($t->mask)
|
|
)
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
$this->vfs_versionsystem->commit($ls_fileonly[0]['file_id']);
|
|
|
|
/* $this->add_journal (array(
|
|
'string' => $t->fake_full_path,
|
|
'relatives' => array ($t->mask),
|
|
'operation' => VFS_OPERATION_MOVED,
|
|
'state_one' => $f->fake_full_path,
|
|
'state_two' => $t->fake_full_path
|
|
)
|
|
);*/
|
|
return True;
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
function rm ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT)
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
if (!$this->acl_check (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'operation' => PHPGW_ACL_DELETE
|
|
))
|
|
)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
if (!$this->file_exists (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
))
|
|
)
|
|
{
|
|
if ($this->file_actions)
|
|
{
|
|
$rr = unlink ($p->real_full_path);
|
|
}
|
|
else
|
|
{
|
|
$rr = True;
|
|
}
|
|
|
|
if ($rr)
|
|
{
|
|
return True;
|
|
}
|
|
else
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
|
|
if ($this->file_type (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)) != 'Directory'
|
|
)
|
|
{
|
|
$ls_array = $this->ls(array(
|
|
'string' => $p->fake_full_path_clean,
|
|
'relatives' => $p->mask
|
|
));
|
|
|
|
$file = $ls_array[0];
|
|
|
|
$this->vfs_versionsystem->save_snapshot($file['file_id'],VFS_OPERATION_DELETED);
|
|
|
|
$query = $GLOBALS['phpgw']->db->query ("DELETE FROM phpgw_vfs2_files WHERE directory='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'", __LINE__, __FILE__);
|
|
|
|
if ($query)
|
|
$this->vfs_versionsystem->commit($file['file_id']);
|
|
|
|
if ($this->file_actions)
|
|
{
|
|
$rr = unlink ($p->real_full_path);
|
|
}
|
|
else
|
|
{
|
|
$rr = True;
|
|
}
|
|
|
|
if ($query || $rr)
|
|
{
|
|
return True;
|
|
}
|
|
else
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$ls = $this->ls (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask)
|
|
)
|
|
);
|
|
|
|
/* First, we cycle through the entries and delete the files */
|
|
foreach($ls as $entry)
|
|
{
|
|
if ($entry['mime_type'] == 'Directory')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$this->rm (array(
|
|
'string' => "$entry[directory]/$entry[name]",
|
|
'relatives' => array ($p->mask)
|
|
)
|
|
);
|
|
}
|
|
|
|
/* Now we cycle through again and delete the directories */
|
|
foreach ($ls as $entry)
|
|
{
|
|
if ($entry['mime_type'] != 'Directory')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/* Only the best in confusing recursion */
|
|
$this->rm (array(
|
|
'string' => "$entry[directory]/$entry[name]",
|
|
'relatives' => array ($p->mask)
|
|
)
|
|
);
|
|
}
|
|
|
|
/* If the directory is linked, we delete the placeholder directory */
|
|
$ls_array = $this->ls (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'checksubdirs' => False,
|
|
'mime_type' => False,
|
|
'nofiles' => True
|
|
)
|
|
);
|
|
$link_info = $ls_array[0];
|
|
|
|
if ($link_info['link_directory'] && $link_info['link_name'])
|
|
{
|
|
$path = $this->path_parts (array(
|
|
'string' => $link_info['directory'] . '/' . $link_info['name'],
|
|
'relatives' => array ($p->mask),
|
|
'nolinks' => True
|
|
)
|
|
);
|
|
|
|
if ($this->file_actions)
|
|
{
|
|
rmdir ($path->real_full_path);
|
|
}
|
|
}
|
|
|
|
$file = $link_info;
|
|
|
|
$this->vfs_versionsystem->save_snapshot($file['file_id'],VFS_OPERATION_DELETED);
|
|
|
|
$query = $GLOBALS['phpgw']->db->query ("DELETE FROM phpgw_vfs2_files WHERE directory='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'",
|
|
__LINE__, __FILE__);
|
|
|
|
if ($query)
|
|
$this->vfs_versionsystem->commit();
|
|
|
|
if ($this->file_actions)
|
|
{
|
|
rmdir ($p->real_full_path);
|
|
}
|
|
|
|
return True;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
function mkdir ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT)
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$account_id = $GLOBALS['phpgw_info']['user']['account_id'];
|
|
$currentapp = $GLOBALS['phpgw_info']['flags']['currentapp'];
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
if (!$this->acl_check (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'operation' => PHPGW_ACL_ADD)
|
|
)
|
|
)
|
|
{
|
|
echo "can't create dir ".$p->fake_full_path." due to permissions.";
|
|
return False;
|
|
}
|
|
|
|
/* We don't allow /'s in dir names, of course */
|
|
if (ereg ("/", $p->fake_name))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
umask (077);
|
|
|
|
if ($this->file_actions)
|
|
{
|
|
if (!@is_dir($p->real_leading_dirs_clean)) // eg. /home or /group does not exist
|
|
{
|
|
if (!ereg_replace('^/','',$p->fake_leading_dirs))
|
|
{
|
|
return false;
|
|
}
|
|
if (!@$this->mkdir(array(
|
|
'string' => $p->fake_leading_dirs,
|
|
'relatives' => array(RELATIVE_NONE) ))) // ==> create it
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
|
|
if (@is_dir($p->real_full_path)) // directory already exists
|
|
{
|
|
//WITH Serious BUG when registrys are in database, but not
|
|
//in filesystem. Correct this ASAP.
|
|
//$this->update_real($data,True); // update its contents
|
|
}
|
|
elseif (!@mkdir ($p->real_full_path, 0770))
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
|
|
if (!$this->file_exists (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask)
|
|
))
|
|
)
|
|
{
|
|
$query = $GLOBALS['phpgw']->db->query ("INSERT INTO phpgw_vfs2_files (owner_id, name, directory) VALUES ($this->working_id, '".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."', '".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."')", __LINE__, __FILE__);
|
|
|
|
$this->set_attributes(array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'attributes' => array (
|
|
'createdby_id' => $account_id,
|
|
'size' => 4096,
|
|
'mime_type' => 'Directory',
|
|
'created' => $this->now,
|
|
'deleteable' => 'Y',
|
|
'app' => $currentapp
|
|
)
|
|
)
|
|
);
|
|
|
|
$this->correct_attributes (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask)
|
|
)
|
|
);
|
|
|
|
//Get info to the versionsystem
|
|
$res = $this->ls(array(
|
|
'string' => $p->fake_full_path_clean,
|
|
'relatives' => $p->mask
|
|
));
|
|
|
|
$file = $res[0];
|
|
|
|
$this->vfs_versionsystem->create_initial_version($file['file_id']);
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
return False;
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
function make_link ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT, RELATIVE_CURRENT)
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$account_id = $GLOBALS['phpgw_info']['user']['account_id'];
|
|
$currentapp = $GLOBALS['phpgw_info']['flags']['currentapp'];
|
|
|
|
$vp = $this->path_parts (array(
|
|
'string' => $data['vdir'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
$rp = $this->path_parts (array(
|
|
'string' => $data['rdir'],
|
|
'relatives' => array ($data['relatives'][1])
|
|
)
|
|
);
|
|
|
|
if (!$this->acl_check (array(
|
|
'string' => $vp->fake_full_path,
|
|
'relatives' => array ($vp->mask),
|
|
'operation' => PHPGW_ACL_ADD
|
|
))
|
|
)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
|
|
if ((!$this->file_exists (array(
|
|
'string' => $rp->real_full_path,
|
|
'relatives' => array ($rp->mask)
|
|
)))
|
|
&& !mkdir ($rp->real_full_path, 0770))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
if (!$this->mkdir (array(
|
|
'string' => $vp->fake_full_path,
|
|
'relatives' => array ($vp->mask)
|
|
))
|
|
)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
$size = $this->get_size (array(
|
|
'string' => $rp->real_full_path,
|
|
'relatives' => array ($rp->mask)
|
|
)
|
|
);
|
|
|
|
$this->set_attributes(array(
|
|
'string' => $vp->fake_full_path,
|
|
'relatives' => array ($vp->mask),
|
|
'attributes' => array (
|
|
'link_directory' => $rp->real_leading_dirs,
|
|
'link_name' => $rp->real_name,
|
|
'size' => $size
|
|
)
|
|
)
|
|
);
|
|
|
|
$this->correct_attributes (array(
|
|
'string' => $vp->fake_full_path,
|
|
'relatives' => array ($vp->mask)
|
|
)
|
|
);
|
|
|
|
return True;
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
//upd 2004-09-16 viniciuscb: custom fields support
|
|
//upd 2004-10-11 viniciuscb: proper_id for file: accepts:
|
|
// $data['proper_id'], for an all-ready proper id, else
|
|
// $data['prefix'] for a string with the prefix
|
|
// (this can only be used if no proper_id
|
|
// specified now or before)
|
|
// $data['ptype'] For a specification of file type
|
|
// $data['prefix_type'] (FUTURE)
|
|
// if none specified, prefix will be user_lid
|
|
function set_attributes ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT),
|
|
'attributes' => array ()
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
/*
|
|
* This is kind of trivial, given that set_attributes () can change
|
|
* owner_id, size, etc.
|
|
*/
|
|
if (!$this->acl_check (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'operation' => PHPGW_ACL_EDIT
|
|
))
|
|
)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
if (!$this->file_exists (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
))
|
|
)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
/*
|
|
* All this voodoo just decides which attributes to update
|
|
* depending on if the attribute was supplied in the 'attributes'
|
|
* array
|
|
*/
|
|
|
|
$ls_array = $this->ls (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'checksubdirs' => False,
|
|
'nofiles' => True
|
|
)
|
|
);
|
|
$record = $ls_array[0];
|
|
|
|
//handles mime type
|
|
|
|
/* FIXME is mime_type is application/octet-stream, don't believe
|
|
* in passed mime_type and try to find a mime type based in
|
|
* extension */
|
|
/* TODO use mime magic capabilities */
|
|
$mime_id = '';
|
|
if ($data['attributes']['mime_type'] && $data['attributes']['mime_type'] != 'application/octet-stream')
|
|
{
|
|
$mime_data = array (
|
|
'mime' => $data['attributes']['mime_type'],
|
|
'extension' => @$this->get_file_extension($data['string'])
|
|
);
|
|
|
|
if (!$type = $this->vfs_mimetypes->get_type($mime_data))
|
|
{
|
|
$type = $this->vfs_mimetypes->add_filetype($mime_data);
|
|
}
|
|
}
|
|
//try to find a compatible mime/type based in file extension
|
|
else
|
|
{
|
|
$mime_data = array (
|
|
'extension' => @$this->get_file_extension($data['string'])
|
|
);
|
|
|
|
if (!$type = $this->vfs_mimetypes->get_type($mime_data))
|
|
{
|
|
$type = $this->vfs_mimetypes->add_filetype($mime_data);
|
|
|
|
}
|
|
|
|
/* Finally if the file has no extension and no mime (or mime
|
|
* defined as application/octet-stream, will consider file type
|
|
* as application/octet-stream
|
|
*/
|
|
if (!$type)
|
|
{
|
|
$type = $this->vfs_mimetypes->get_type(array(
|
|
'mime' => 'application/octet-stream'
|
|
));
|
|
}
|
|
|
|
}
|
|
|
|
//will only change mime_type if mime_type was specified in attribts
|
|
if ($data['attributes']['mime_type'])
|
|
{
|
|
unset($data['attributes']['mime_type']);
|
|
$data['attributes']['mime_id'] = $type['mime_id'];
|
|
}
|
|
|
|
/*
|
|
Indicate that the EDITED_COMMENT operation needs to be journaled,
|
|
but only if the comment changed
|
|
*/
|
|
if (array_key_exists('comment',$data['attributes']) &&
|
|
$data['attributes']['comment'] != $record['comment'])
|
|
{
|
|
$edited_comment = 1;
|
|
}
|
|
|
|
#** proper id treating **
|
|
|
|
#1.User does not specified proper_id, and file had not any proper id
|
|
#generates a new proper_id
|
|
if(!$data['attributes']['proper_id'] && $data['attributes']['prefix'])
|
|
{
|
|
$prefix = $data['attributes']['prefix'];
|
|
|
|
// $data['attributes']['proper_id'] = $this->generate_proper_id($data['attributes']['prefix'],$type['proper_id']);
|
|
$data['attributes']['proper_id'] = $this->generate_proper_id($data['attributes']['prefix'],$data['attributes']['ptype']);
|
|
}
|
|
#2.User specified proper_id
|
|
#check if this id is not being used. If it is, do not change.
|
|
elseif ($data['attributes']['proper_id'])
|
|
{
|
|
$this->db->select('phpgw_vfs2_files','proper_id',array('proper_id'=>$data['attributes']['proper_id']));
|
|
|
|
if ($this->db->next_record())
|
|
{
|
|
unset($data['attributes']['proper_id']);
|
|
}
|
|
|
|
}
|
|
|
|
//To be sure that olny fields from phpgw_vfs2_files will be inserted
|
|
$update_data = array();
|
|
foreach ($data['attributes'] as $key => $val)
|
|
{
|
|
if ($this->attribute_tables[$key] == 'phpgw_vfs2_files' || $key == 'mime_id')
|
|
$update_data[$key] = $val;
|
|
}
|
|
|
|
$where = array(
|
|
'file_id' => $record['file_id']
|
|
);
|
|
|
|
if ($edited_comment)
|
|
{
|
|
$this->vfs_versionsystem->save_snapshot($record['file_id'],
|
|
VFS_OPERATION_EDITED_COMMENT);
|
|
}
|
|
|
|
if (count($update_data)) //if false, there is nothing to do
|
|
{
|
|
$res = $this->db->update('phpgw_vfs2_files',$update_data,$where,
|
|
__LINE__,__FILE__);
|
|
|
|
if ($res)
|
|
{
|
|
//custom fields storing
|
|
$customfields = $this->vfs_customfields->get_customfields('customfield_name');
|
|
foreach ($customfields as $custom_name => $custom_val)
|
|
{
|
|
if (array_key_exists($custom_name,$data['attributes']))
|
|
{
|
|
$store_array[$record['file_id']][$custom_name] = $data['attributes'][$custom_name];
|
|
|
|
}
|
|
}
|
|
|
|
if ($store_array)
|
|
{
|
|
$this->vfs_customfields->store_fields($store_array);
|
|
}
|
|
|
|
if ($edited_comment)
|
|
{
|
|
$this->vfs_versionsystem->commit($record['file_id']);
|
|
}
|
|
return True;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*!
|
|
@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 ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT)
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
if ($p->fake_leading_dirs != $this->fakebase && $p->fake_leading_dirs != '/')
|
|
{
|
|
$ls_array = $this->ls (array(
|
|
'string' => $p->fake_leading_dirs,
|
|
'relatives' => array ($p->mask),
|
|
'checksubdirs' => False,
|
|
'nofiles' => True
|
|
)
|
|
);
|
|
$set_attributes_array = Array(
|
|
'owner_id' => $ls_array[0]['owner_id']
|
|
);
|
|
}
|
|
elseif (preg_match ("+^$this->fakebase\/(.*)$+U", $p->fake_full_path, $matches))
|
|
{
|
|
$set_attributes_array = Array(
|
|
'owner_id' => $GLOBALS['phpgw']->accounts->name2id ($matches[1])
|
|
);
|
|
}
|
|
else
|
|
{
|
|
$set_attributes_array = Array(
|
|
'owner_id' => 0
|
|
);
|
|
}
|
|
|
|
$this->set_attributes (array(
|
|
'string' => $p->fake_full_name,
|
|
'relatives' => array ($p->mask),
|
|
'attributes' => $set_attributes_array
|
|
)
|
|
);
|
|
|
|
return True;
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
function file_type ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT)
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
if (!$this->acl_check (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'operation' => PHPGW_ACL_READ,
|
|
'must_exist' => 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
|
|
*/
|
|
|
|
//TODO VCB change this also with filetypes class
|
|
|
|
$db2 = $GLOBALS['phpgw']->db;
|
|
|
|
$db2->query ("SELECT mime_id
|
|
FROM phpgw_vfs2_files
|
|
WHERE directory='".$db2->db_addslashes($p->fake_leading_dirs_clean)."'
|
|
AND name='".$db2->db_addslashes($p->fake_name_clean)."'", __LINE__, __FILE__);
|
|
$db2->next_record ();
|
|
|
|
$file_record = $db2->Record;
|
|
|
|
$mime = $this->vfs_mimetypes->get_type(array(
|
|
'mime_id' => $file_record['mime_id']
|
|
));
|
|
|
|
$mime_type = $mime['mime'];
|
|
|
|
if(!$mime_type)
|
|
{
|
|
$extension = $this->get_file_extension($p->fake_name_clean);
|
|
|
|
if (!$res = $this->vfs_mimetypes->get_type(array(
|
|
'extension' => $extension)) )
|
|
{
|
|
$res = $this->vfs_mimetypes->add_filetype(array(
|
|
'extension' => $extension));
|
|
|
|
if ($res)
|
|
{
|
|
$this->db->update('phpgw_vfs2_files',
|
|
array('mime_id' => $res['mime_id']),
|
|
array('directory' => $p->fake_leading_dirs_clean,
|
|
'name' => $p->fake_name_clean
|
|
),__LINE__,__FILE__);
|
|
}
|
|
|
|
}
|
|
$mime_type = $res['mime'];
|
|
|
|
}
|
|
|
|
return $mime_type;
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
function file_exists ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT),
|
|
'allow_outside' => true
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
if ($p->outside)
|
|
{
|
|
if (!$data['allow_outside'])
|
|
{
|
|
return false;
|
|
}
|
|
$rr = file_exists ($p->real_full_path);
|
|
|
|
return $rr;
|
|
}
|
|
|
|
//TODO id: primary field
|
|
$db2 =& $GLOBALS['phpgw']->db;
|
|
$db2->query ("SELECT name FROM phpgw_vfs2_files WHERE directory='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'", __LINE__, __FILE__);
|
|
|
|
if ($db2->num_rows())
|
|
{
|
|
return True;
|
|
}
|
|
else
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
function get_size ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT),
|
|
'checksubdirs' => True
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
if (!$this->acl_check (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'operation' => PHPGW_ACL_READ,
|
|
'must_exist' => 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;
|
|
}
|
|
|
|
foreach($this->ls (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'checksubdirs' => $data['checksubdirs'],
|
|
'nofiles' => !$data['checksubdirs']
|
|
)) as $file_array)
|
|
{
|
|
/*
|
|
Make sure the file is in the directory we want, and not
|
|
some deeper nested directory with a similar name
|
|
*/
|
|
/*
|
|
if (@!ereg ('^' . $file_array['directory'], $p->fake_full_path))
|
|
{
|
|
continue;
|
|
}
|
|
*/
|
|
|
|
$size += $file_array['size'];
|
|
}
|
|
|
|
//TODO VCB update this when id be primary key
|
|
if ($data['checksubdirs'])
|
|
{
|
|
$query = $GLOBALS['phpgw']->db->query ("SELECT size FROM phpgw_vfs2_files WHERE directory='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'",__LINE__,__FILE__);
|
|
$GLOBALS['phpgw']->db->next_record ();
|
|
$size += $GLOBALS['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 string Directory to check access of
|
|
@param relatives Relativity array
|
|
@result Boolean True/False
|
|
*/
|
|
function checkperms ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT)
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
if (!$this->acl_check (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask),
|
|
'operation' => PHPGW_ACL_ADD
|
|
))
|
|
)
|
|
{
|
|
return False;
|
|
}
|
|
else
|
|
{
|
|
return True;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
* If $data['readlink'] then a readlink is tryed on the real file
|
|
* If $data['file_id'] then the file_id is used instead of a path
|
|
*/
|
|
//upd 2004-09-16 viniciuscb: Support for custom fields
|
|
function ls ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT),
|
|
'checksubdirs' => True,
|
|
'mime_type' => False,
|
|
'nofiles' => False,
|
|
'orderby' => 'directory,name',
|
|
'backups' => false, /* show or hide backups */
|
|
'files_specified' => array(),
|
|
'allow_outside' => true,
|
|
'modifiedby_information' => false
|
|
);
|
|
|
|
//check if orderby is a valid field (or is composed by valid fields)
|
|
//this prevents a sql error that happens when sort field is invalid.
|
|
if ($data['orderby'])
|
|
{
|
|
$fields = explode(',',$data['orderby']);
|
|
foreach ($fields as $field_name)
|
|
{
|
|
if ($this->attribute_tables[trim($field_name)] != 'phpgw_vfs2_files')
|
|
{
|
|
unset($data['orderby']);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
$dir = $p->fake_full_path;
|
|
|
|
//Abiliy to show or not backup files -> put it in sql queries
|
|
$sql_backups = ($data['backups']) ? '' : ' AND is_backup=\'N\' ';
|
|
|
|
|
|
/* If they pass us a file or 'nofiles' is set, return the info for $dir only */
|
|
if (@$data['file_id']
|
|
|| ((($type = $this->file_type (array(
|
|
'string' => $dir,
|
|
'relatives' => array ($p->mask)
|
|
)) != 'Directory'))
|
|
|| ($data['nofiles'])) && !$p->outside
|
|
)
|
|
{
|
|
|
|
/* SELECT all, the, attributes */
|
|
$sql = 'SELECT ';
|
|
|
|
foreach ($this->attributes as $num => $attribute)
|
|
{
|
|
if ($this->attribute_tables[$attribute] == 'phpgw_vfs2_files')
|
|
{
|
|
if ($num)
|
|
{
|
|
$sql .= ', ';
|
|
}
|
|
|
|
$sql .= $attribute;
|
|
}
|
|
}
|
|
|
|
$sql .= ",mime_id,is_backup FROM phpgw_vfs2_files WHERE ";
|
|
|
|
|
|
if (@$data['file_id'])
|
|
{
|
|
$sql .= 'file_id='.(int)$data['file_id'].$sql_backups;
|
|
}
|
|
else
|
|
{
|
|
$sql .= "directory='".$GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean).
|
|
"' AND name='".$GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'".$sql_backups;
|
|
}
|
|
|
|
// echo " select1: dir=".$p->fake_leading_dirs_clean." name=".$p->fake_name_clean." <br>\n";
|
|
$query = $GLOBALS['phpgw']->db->query ($sql, __LINE__, __FILE__);
|
|
|
|
$GLOBALS['phpgw']->db->next_record ();
|
|
$record = $GLOBALS['phpgw']->db->Record;
|
|
|
|
if (!$record)
|
|
{
|
|
return array();
|
|
}
|
|
|
|
/* We return an array of one array to maintain the standard */
|
|
$rarray = array ();
|
|
foreach($this->attributes as $attribute)
|
|
{
|
|
switch ($attribute)
|
|
{
|
|
|
|
case 'mime_type':
|
|
if (!is_numeric($record['mime_id']))
|
|
{
|
|
//no mime type registered for file, must find one and if not exist add one.
|
|
$extension = $this->get_file_extension($record['name']);
|
|
|
|
if (!$res = $this->vfs_mimetypes->get_type(array('extension' => $extension)))
|
|
{
|
|
$res = $this->vfs_mimetypes->add_filetype(array('extension' => $extension));
|
|
}
|
|
|
|
if ($res)
|
|
{
|
|
$this->db->update('phpgw_vfs2_files',
|
|
array('mime_id' => $res['mime_id']),
|
|
array('directory' => $p->fake_leading_dirs_clean,
|
|
'name' => $p->fake_name_clean
|
|
),__LINE__,__FILE__);
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$res = $this->vfs_mimetypes->get_type(array(
|
|
'mime_id' => $record['mime_id']
|
|
));
|
|
}
|
|
|
|
$record['mime_type'] = $res['mime'];
|
|
$record['mime_friendly'] = $res['friendly'];
|
|
break;
|
|
case 'created':
|
|
case 'modified':
|
|
$record[$attribute] = $this->db->from_timestamp($record[$attribute]);
|
|
break;
|
|
}
|
|
|
|
|
|
$rarray[0][$attribute] = $record[$attribute];
|
|
}
|
|
if ($this->file_actions && @$data['readlink']) // test if file is a symlink and get it's target
|
|
{
|
|
$rarray[0]['symlink'] = @readlink($p->real_full_path);
|
|
}
|
|
|
|
//handle custom fields
|
|
reset($rarray);
|
|
while(list($key,$val) = each($rarray))
|
|
{
|
|
$custom =& $this->vfs_customfields->get_fields_by_fileid($val['file_id']);
|
|
|
|
if ($custom)
|
|
{
|
|
$rarray[$key] = array_merge($val,$custom);
|
|
}
|
|
}
|
|
|
|
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 (!$data['allow_outside'])
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ($this->file_type (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array ($p->mask)
|
|
)) == 'Directory'
|
|
&& !$data['nofiles']
|
|
)
|
|
{
|
|
$dir_handle = opendir ($p->real_full_path);
|
|
while ($filename = readdir ($dir_handle))
|
|
{
|
|
if ($filename == '.' || $filename == '..')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$rarray[] = $this->get_real_info (array(
|
|
'string' => $p->real_full_path . SEP . $filename,
|
|
'relatives' => array ($p->mask)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$rarray[] = $this->get_real_info (array(
|
|
'string' => $p->real_full_path,
|
|
'relatives' => array ($p->mask)
|
|
)
|
|
);
|
|
}
|
|
|
|
//handle custom fields
|
|
reset($rarray);
|
|
while(list($key,$val) = each($rarray))
|
|
{
|
|
$custom =& $this->vfs_customfields->get_fields_by_fileid($val['file_id']);
|
|
|
|
if ($custom)
|
|
{
|
|
$rarray[$key] = array_merge($val,$custom);
|
|
}
|
|
}
|
|
|
|
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 */
|
|
|
|
// echo "DIR_CLEAN: ".$dir_clean."<BR>";
|
|
|
|
$dir_clean = $this->clean_string (array ('string' => $dir));
|
|
|
|
|
|
//This query must be fast and only bring things with the correct
|
|
//permissions. So, I'll get the list of all groups the current user
|
|
//belongs, get the list of the current dir and all parents over it
|
|
//and pass all these things in one query.
|
|
|
|
//gets the id of all groups $account_id belongs to
|
|
$groups = $GLOBALS['phpgw']->accounts->membership($GLOBALS['phpgw_info']['user']['account_id']);
|
|
|
|
foreach($groups as $group)
|
|
{
|
|
$accounts[] = $group['account_id'];
|
|
}
|
|
|
|
$accounts[] = $GLOBALS['phpgw_info']['user']['account_id'];
|
|
$accounts[] = 0; //default permission for all users
|
|
|
|
$paths = array();
|
|
|
|
$dir_exploded = explode('/',$dir_clean);
|
|
$dir_parts = count($dir_parts);
|
|
|
|
for ($i=$dir_parts-1;$i>=0;$i--)
|
|
{
|
|
$res = implode('/',array_slice($dir_explode,0,$i));
|
|
$paths[] = "'".($res) ? $res : '/'."'";
|
|
}
|
|
|
|
if (!$data['backups'])
|
|
{
|
|
$append .= " AND fls.is_backup = 'N'";
|
|
}
|
|
|
|
|
|
if ($data['mime_type'])
|
|
{
|
|
$other_where .= " AND mime.mime = '".$data['mime_type']."'";
|
|
$mime_join = ' INNER JOIN phpgw_vfs2_mimetypes mime ON fls.mime_id = mime.mime_id';
|
|
}
|
|
|
|
//orderby
|
|
$orderby = explode(',',$data['orderby']);
|
|
|
|
foreach($orderby as $key =>$orderby_instance)
|
|
{
|
|
$orderby[$key] = 'fls.'.$orderby_instance;
|
|
}
|
|
|
|
|
|
$append .= ' ORDER BY '.implode(',',$orderby);
|
|
|
|
$dir_rule = $data['checksubdirs'] ? "fls.directory LIKE '".$dir_clean."%'" : "fls.directory = '".$dir_clean."'";
|
|
//SQL to get all files in current dir, except those ones that user
|
|
//does not have permission to see
|
|
$sql = "SELECT DISTINCT fls.*
|
|
FROM phpgw_vfs2_files fls
|
|
$mime_join
|
|
LEFT JOIN phpgw_vfs2_shares sh ON fls.file_id = sh.file_id
|
|
WHERE ".$dir_rule." AND
|
|
( (sh.account_id in (".implode(',',$accounts).") AND fls.shared = 'Y') OR
|
|
(sh.account_id is NULL AND fls.shared = 'N') OR
|
|
fls.owner_id = ".$GLOBALS['phpgw_info']['user']['account_id']." )
|
|
$other_where $append";
|
|
|
|
|
|
// echo "<xmp>\n$sql\n</xmp>";
|
|
|
|
$query = $GLOBALS['phpgw']->db->query ($sql, __LINE__, __FILE__);
|
|
|
|
$rarray = array ();
|
|
for ($i = 0; $GLOBALS['phpgw']->db->next_record (); $i++)
|
|
{
|
|
$record = $GLOBALS['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']))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/* If they want only this directory, then $dir should end without a trailing / */
|
|
if (!$data['checksubdirs'] && ereg ("^$dir/", $record['directory']))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
foreach($this->attributes as $attribute)
|
|
{
|
|
switch($attribute)
|
|
{
|
|
case 'mime_type':
|
|
if (!is_numeric($record['mime_id']))
|
|
{
|
|
$extension = $this->get_file_extension($record['name']);
|
|
if(!$res = $this->vfs_mimetypes->get_type(array(
|
|
'extension' => $extension)) )
|
|
{
|
|
$res = $this->vfs_mimetypes->add_filetype(array(
|
|
'extension'
|
|
));
|
|
|
|
if ($res)
|
|
{
|
|
$this->db->update('phpgw_vfs2_files',
|
|
array('mime_id' => $res['mime_id']),
|
|
array('directory' => $p->fake_leading_dirs_clean,
|
|
'name' => $p->fake_name_clean
|
|
),__LINE__,__FILE__);
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$res = $this->vfs_mimetypes->get_type(array(
|
|
'mime_id' => $record['mime_id']
|
|
));
|
|
}
|
|
|
|
$record['mime_type'] = $res['mime'];
|
|
$rarray[$i]['mime_friendly'] = $res['friendly'];
|
|
break;
|
|
case 'created':
|
|
case 'modified':
|
|
$record[$attribute] = $this->db->from_timestamp($record[$attribute]);
|
|
break;
|
|
}
|
|
|
|
$rarray[$i][$attribute] = $record[$attribute];
|
|
}
|
|
}
|
|
|
|
//handle custom fields
|
|
reset($rarray);
|
|
while(list($key,$val) = each($rarray))
|
|
{
|
|
$custom =& $this->vfs_customfields->get_fields_by_fileid($val['file_id']);
|
|
|
|
if ($custom)
|
|
{
|
|
$rarray[$key] = array_merge($val,$custom);
|
|
}
|
|
}
|
|
|
|
return $rarray;
|
|
}
|
|
|
|
/*
|
|
* See vfs_shared
|
|
*/
|
|
function update_real ($data,$recursive = False)
|
|
{
|
|
//FIXME this method does not work when there are registrys in
|
|
//database, but not in filesystem. It starts corromping the
|
|
//database by putting wrong things that are in the partition root.
|
|
//return false;
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT)
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['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 ($filename == '.' || $filename == '..')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$rarray[] = $this->get_real_info (array(
|
|
'string' => $p->fake_full_path . '/' . $filename,
|
|
'relatives' => array (RELATIVE_NONE)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$rarray[] = $this->get_real_info (array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => array (RELATIVE_NONE)
|
|
)
|
|
);
|
|
}
|
|
|
|
if (!is_array ($rarray))
|
|
{
|
|
$rarray = array ();
|
|
}
|
|
|
|
foreach($rarray as $num => $file_array)
|
|
{
|
|
$p2 = $this->path_parts (array(
|
|
'string' => $file_array['directory'] . '/' . $file_array['name'],
|
|
'relatives' => 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 (array(
|
|
'string' => $p2->fake_full_path,
|
|
'relatives' => array (RELATIVE_NONE)
|
|
))
|
|
)
|
|
{
|
|
$this->touch (array(
|
|
'string' => $p2->fake_full_path,
|
|
'relatives' => array (RELATIVE_NONE)
|
|
)
|
|
);
|
|
}
|
|
$this->set_attributes (array(
|
|
'string' => $p2->fake_full_path,
|
|
'relatives' => array (RELATIVE_NONE),
|
|
'attributes' => $set_attributes_array
|
|
)
|
|
);
|
|
if ($recursive && $file_array['mime_type'] == 'Directory')
|
|
{
|
|
$dir_data = $data;
|
|
$dir_data['string'] = $file_array['directory'] . '/' . $file_array['name'];
|
|
$this->update_real($dir_data,$recursive);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* @function regenerate_database
|
|
* @abstract This function regenerates the full database. It is like
|
|
* the function update_real, but instead, it works for all files in a
|
|
* folder, fixing all broken regs in a database (if it exists), or
|
|
* recreating it.
|
|
* @author Vinicius Cubas Brand
|
|
*/
|
|
function regenerate_database()
|
|
{
|
|
|
|
}
|
|
|
|
/* Helper functions */
|
|
|
|
/* This fetchs all available file system information for string (not using the database) */
|
|
function get_real_info ($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT)
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
if (is_dir ($p->real_full_path))
|
|
{
|
|
$mime_type = 'Directory';
|
|
}
|
|
else
|
|
{
|
|
$mime_type = $this->get_ext_mime_type (array(
|
|
'string' => $p->fake_name
|
|
)
|
|
);
|
|
|
|
/* if($mime_type)
|
|
{
|
|
$GLOBALS['phpgw']->db->query ("UPDATE phpgw_vfs2_files as file, phpgw_vfs2_mimetypes as mime SET mime.mime_id=file.mime_id WHERE mime.mime='".$mime_type."' AND file.directory='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND file.name='".
|
|
$GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'",
|
|
__LINE__, __FILE__);
|
|
}*/
|
|
}
|
|
|
|
$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);
|
|
}
|
|
|
|
|
|
/*!
|
|
* @function search
|
|
* @abstract This function returns the files that have a field with
|
|
* keyword
|
|
*
|
|
* @author Vinicius Cubas Brand
|
|
*/
|
|
function search($keyword,$fields=null,$is_backup='N')
|
|
{
|
|
//the fields in which the keyword will be searched
|
|
$searchable_fields = array(
|
|
'created',
|
|
'comment',
|
|
'app',
|
|
'directory',
|
|
'name',
|
|
'link_directory',
|
|
'link_name',
|
|
'version',
|
|
'proper_id'
|
|
);
|
|
|
|
if (is_array($fields))
|
|
{
|
|
$tmp = array_diff($searchable_fields,$fields);
|
|
$searchable_fields = array_diff($searchable_fields,$tmp);
|
|
}
|
|
|
|
foreach ($searchable_fields as $val)
|
|
{
|
|
$sf[] = $val." LIKE '%$keyword%'";
|
|
}
|
|
|
|
$where = implode(' OR ',$sf);
|
|
|
|
$sql = "SELECT file_id
|
|
FROM phpgw_vfs2_files
|
|
WHERE $where
|
|
AND is_backup = '$is_backup'";
|
|
|
|
$this->db->query($sql,__LINE__,__FILE__);
|
|
|
|
$res = array();
|
|
while ($this->db->next_record())
|
|
{
|
|
$res[] = $this->db->Record['file_id'];
|
|
}
|
|
|
|
//search in the custom fields
|
|
$res = array_unique(array_merge($res,$this->vfs_customfields->search_files($keyword,$fields)));
|
|
|
|
sort($res);
|
|
|
|
return $res;
|
|
}
|
|
|
|
/*!
|
|
* @function get_file_extension
|
|
* @abstract This function returns the file extension for a file.
|
|
*
|
|
* @author Vinicius Cubas Brand
|
|
*/
|
|
function get_file_extension($filename)
|
|
{
|
|
$ext = explode('.',$filename);
|
|
|
|
$bla = array_pop($ext);
|
|
|
|
if (count($ext))
|
|
{
|
|
return $bla;
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
/*!
|
|
* @function get_file_id
|
|
* @abstract This function returns the file id for a file, false on eror
|
|
* @param string, relatives
|
|
*
|
|
* @author Vinicius Cubas Brand
|
|
*/
|
|
function get_file_id($data)
|
|
{
|
|
if (!is_array ($data))
|
|
{
|
|
$data = array ();
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array (RELATIVE_CURRENT),
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
$p = $this->path_parts (array(
|
|
'string' => $data['string'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
)
|
|
);
|
|
|
|
$sql = "SELECT file_id
|
|
FROM phpgw_vfs2_files
|
|
WHERE directory='".$this->db->db_addslashes($p->fake_leading_dirs_clean)."'
|
|
AND name='".$this->db->db_addslashes($p->fake_name_clean)."'";
|
|
|
|
$query = $this->db->query ($sql , __LINE__, __FILE__);
|
|
$this->db->next_record ();
|
|
|
|
return $this->db->Record['file_id'];
|
|
}
|
|
|
|
/*!
|
|
* @function id2name
|
|
* @abstract This function returns an array with all information about
|
|
* a file
|
|
* @param string, relatives
|
|
*
|
|
* @author Vinicius Cubas Brand
|
|
*/
|
|
function id2name($id)
|
|
{
|
|
$res = $this->db->select('phpgw_vfs2_files','*',
|
|
array('file_id'=>$id),__LINE__,__FILE__);
|
|
|
|
if($this->db->next_record())
|
|
{
|
|
$result = $this->db->Record;
|
|
|
|
$res = $this->vfs_mimetypes->get_type(array(
|
|
'mime_id' => $result['mime_id']
|
|
));
|
|
|
|
$result['mime_type'] = $res['mime'];
|
|
$result['mime_friendly'] = $res['friendly'];
|
|
|
|
return $result;
|
|
}
|
|
|
|
return array();
|
|
}
|
|
|
|
//TODO should generate a new name if archive exists, or have some other
|
|
//sort of smart error handling.
|
|
function compress($data)
|
|
{
|
|
$compression_handlers = array(
|
|
// 'gz' => 'gzip',
|
|
// 'bz2' => 'bzip',
|
|
// 'tar' => 'tar',
|
|
'zip' => 'zip'
|
|
);
|
|
|
|
if (!is_array($data['files']) || !$data['name'])
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'type' => 'zip',
|
|
'relatives' => array(RELATIVE_CURRENT),
|
|
'prefix' => $GLOBALS['phpgw_info']['user']['account_lid'],
|
|
'ptype' => ''
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
if (!$data['type'] || !array_key_exists($data['type'],$compression_handlers))
|
|
{
|
|
//error: inexistent type given
|
|
return false;
|
|
}
|
|
|
|
|
|
//put extension in archive name, if not exists
|
|
if ($this->get_file_extension($data['name']) != $data['type'])
|
|
{
|
|
if ($data['type'] == 'zip' || $data['type'] == 'tar')
|
|
{
|
|
$data['name'] .= '.' . $data['type'];
|
|
}
|
|
else
|
|
{
|
|
$data['name'] .= '.tar.' . $data['type'];
|
|
}
|
|
}
|
|
|
|
//last element in array $data['relatives'] is the id of destiny
|
|
$dest_relativity = (count($data['relatives']))?array_pop($data['relatives']):RELATIVE_CURRENT;
|
|
|
|
$dest = $this->path_parts(array(
|
|
'string' => $data['name'],
|
|
'relatives' => $dest_relativity
|
|
));
|
|
|
|
if ($this->file_exists(array(
|
|
'string' => $dest->fake_full_path,
|
|
'relatives' => $dest->mask )))
|
|
{
|
|
//overwrite handling
|
|
|
|
//check if acl allow overwriting
|
|
if (!$this->acl_check(array(
|
|
'string' => $dest->fake_full_path,
|
|
'relatives' => $dest->mask,
|
|
'operation' => PHPGW_ACL_EDIT))
|
|
)
|
|
{
|
|
//error: cannot overwrite (HANDLE THIS)
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Add handling
|
|
|
|
//check acl
|
|
if (!$this->acl_check(array(
|
|
'string' => $dest->fake_leading_dirs,
|
|
'relatives' => $dest->mask,
|
|
'operation' => PHPGW_ACL_ADD))
|
|
)
|
|
{
|
|
//error: cannot add in dir
|
|
return false;
|
|
}
|
|
}
|
|
|
|
$count_rels = count($data['relatives']);
|
|
|
|
reset($data['relatives']);
|
|
foreach($data['files'] as $filename)
|
|
{
|
|
if (!($relative = current($data['relatives'])))
|
|
{
|
|
$relative = RELATIVE_CURRENT;
|
|
}
|
|
|
|
$p = $this->path_parts(array(
|
|
'string' => $filename,
|
|
'relatives' => array($relative)
|
|
));
|
|
|
|
if ($this->acl_check(array(
|
|
'string' => $p->fake_full_path,
|
|
'relatives' => $p->mask,
|
|
'operation' => PHPGW_ACL_READ,
|
|
'must_exist' => true )) )
|
|
{
|
|
$filenames[] = $p->real_full_path;
|
|
}
|
|
else
|
|
{
|
|
//catch error: file not exists or no permission
|
|
}
|
|
|
|
next($data['relatives']);
|
|
}
|
|
|
|
//Save file in tmp folder, then move it to its definitive place.
|
|
//This will handle file overwrites and journalling entries.
|
|
|
|
$tmp_dir = $GLOBALS['phpgw_info']['server']['temp_dir'];
|
|
$tmp_filename = $tmp_dir.'/'.$this->random_filename();
|
|
|
|
$archive_opts = array(
|
|
'basedir' => $dest->real_leading_dirs,
|
|
'inmemory' => 0,
|
|
'overwrite' => 1, //provisory, todo error handling
|
|
'recurse' => 1,
|
|
'storepaths' => 1,
|
|
'level' => 9//compression level, 9 is max, 0 is none, 3 ok
|
|
);
|
|
|
|
/* #Didn't work - class.archive.inc.php
|
|
$compression_class = $compression_handlers[$data['type']].'_file';
|
|
|
|
require_once(PHPGW_API_INC.'/class.archive.inc.php');
|
|
|
|
$arch = new $compression_class($tmp_filename);
|
|
$arch->set_options($archive_opts);
|
|
$arch->add_files($filenames);
|
|
$arch->create_archive();
|
|
|
|
$type_array = $this->vfs_mimetypes->get_type(array('extension'=>$data['type']));
|
|
$arch_mime = $type_array['mime'];*/
|
|
|
|
|
|
switch($data['type'])
|
|
{
|
|
case 'zip':
|
|
$zip =& CreateObject('phpgwapi.PclZip',$tmp_filename);
|
|
|
|
//FIXME not $dest->real_leading_dirs, but the path to be
|
|
//removed from files
|
|
$zip->create($filenames,PCLZIP_OPT_REMOVE_PATH,$dest->real_leading_dirs);
|
|
$arch_mime = 'application/x-zip-compressed';
|
|
break;
|
|
|
|
default:
|
|
/*
|
|
$tar =& CreateObject('phpgwapi.Archive_Tar',$tmp_filename,$data['type']);
|
|
//FIXME not $dest->real_leading_dirs, but the path to be
|
|
//removed from files
|
|
if (!$tar->createModify($filenames,'',$dest->real_leading_dirs.'/'))
|
|
{
|
|
//TODO throw error
|
|
}
|
|
$arch_mime = 'application/x-gzip';
|
|
break;
|
|
*/
|
|
}
|
|
|
|
/* VOILA! now the archive is created!!! but it is yet in /tmp and
|
|
* have no entry in the database and is not in its correct dir.
|
|
* The next and final step is then to make these tasks. */
|
|
|
|
$dest_relativity = $data['relatives'][count($data['relatives'])-1];
|
|
|
|
# ----------------------------------------------------------- #
|
|
# All code under here copied from filescenter->bo->fileUpload #
|
|
# ----------------------------------------------------------- #
|
|
|
|
$file_comment = "Archive contents:\n\n".implode("\n",$data['files']);
|
|
$file_comment = substr(0,255,$file_comment);
|
|
|
|
# Check to see if the file exists in the database, and get
|
|
# its info at the same time
|
|
$ls_array = $this->ls(array(
|
|
'string'=> $data['name'],
|
|
'relatives' => array($dest_relativity),
|
|
'checksubdirs' => False,
|
|
'nofiles' => True
|
|
));
|
|
|
|
$fileinfo = $ls_array[0];
|
|
|
|
if($fileinfo['name'])
|
|
{
|
|
if($fileinfo['mime_type'] == 'Directory')
|
|
{
|
|
$messages[]= $GLOBALS['phpgw']->common->error_list(array(lang('Cannot replace %1 because it is a directory', $fileinfo['name'])));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
#overwriting
|
|
if($fileinfo['name'] && $fileinfo['deleteable'] != 'N')
|
|
{
|
|
$tmp_arr=array(
|
|
'string'=> $data['name'],
|
|
'relatives' => array($dest_relativity),
|
|
'attributes' => array(
|
|
'owner_id' => $GLOBALS['phpgw_info']['user']['account_id'],
|
|
'modifiedby_id' => $GLOBALS['phpgw_info']['user']['account_id'],
|
|
'modified' => date('Y-m-d'),
|
|
'mime_type' => $arch_mime,
|
|
'size' => filesize($tmp_filename),
|
|
'deleteable' => 'Y',
|
|
'comment' => $file_comment,
|
|
'prefix' => $data['prefix'],
|
|
'ptype' => $data['ptype']
|
|
#if overwriting, do not change.
|
|
#TODO rethink/decide policy for that
|
|
#'prefix' => $otherelms['prefix'.$file_number])
|
|
|
|
)
|
|
);
|
|
$this->set_attributes($tmp_arr);
|
|
|
|
$tmp_arr=array(
|
|
'from' => $tmp_filename,
|
|
'to' => $data['name'],
|
|
'relatives' => array(RELATIVE_NONE|VFS_REAL, $dest_relativity)
|
|
);
|
|
$this->cp($tmp_arr);
|
|
|
|
}
|
|
else #creating a new file
|
|
{
|
|
$this->cp(array(
|
|
'from'=> $tmp_filename,
|
|
'to'=> $data['name'],
|
|
'relatives' => array(RELATIVE_NONE|VFS_REAL, $dest_relativity)
|
|
));
|
|
|
|
$this->set_attributes(array(
|
|
'string'=> $data['name'],
|
|
'relatives' => array($dest_relativity),
|
|
'attributes'=> array(
|
|
'comment' => $file_comment,
|
|
'mime_type' => $arch_mime,
|
|
'prefix' => $data['prefix'],
|
|
'ptype' => $data['ptype']
|
|
|
|
)
|
|
));
|
|
|
|
}
|
|
}
|
|
|
|
|
|
#two parts: 1: extract files in tmp_dir. 2: move files to dir, adding
|
|
# them in db
|
|
function extract($data)
|
|
{
|
|
$compression_handlers = array(
|
|
'gz' => 'gzip',
|
|
'bz2' => 'bzip',
|
|
'tar' => 'tar',
|
|
'zip' => 'zip'
|
|
);
|
|
|
|
|
|
if (!$data['name'] || !$data['dest'])
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$default_values = array
|
|
(
|
|
'relatives' => array(RELATIVE_CURRENT,RELATIVE_CURRENT),
|
|
'prefix' => $GLOBALS['phpgw_info']['user']['account_lid'],
|
|
'ptype' => ''
|
|
|
|
);
|
|
|
|
$data = array_merge ($this->default_values ($data, $default_values), $data);
|
|
|
|
if (!$data['type'])
|
|
{
|
|
$data['type'] = strtolower($this->get_file_extension($data['name']));
|
|
}
|
|
|
|
if (!$data['type'] || !array_key_exists($data['type'],$compression_handlers))
|
|
{
|
|
//error: inexistent type given
|
|
return false;
|
|
}
|
|
|
|
|
|
$arch = $this->path_parts (array(
|
|
'string' => $data['name'],
|
|
'relatives' => array ($data['relatives'][0])
|
|
));
|
|
|
|
$dest = $this->path_parts (array(
|
|
'string' => $data['dest'],
|
|
'relatives' => array_pop($data['relatives'])
|
|
));
|
|
|
|
//Extract files in tmp folder, then move it to its definitive place.
|
|
//This will handle file overwrites and journalling entries.
|
|
|
|
$tmp_dir = $GLOBALS['phpgw_info']['server']['temp_dir'];
|
|
$tmp_dirname = $tmp_dir.'/'.$this->random_filename();
|
|
|
|
|
|
$tmp_dest = $this->path_parts(array(
|
|
'string' => $tmp_dirname,
|
|
'relatives' => array(RELATIVE_NONE|VFS_REAL)
|
|
));
|
|
|
|
if ($this->file_exists(array(
|
|
'string'=> $tmp_dest->fake_full_path,
|
|
'relatives' => $tmp_dest->mask )))
|
|
{
|
|
$this->rm(array(
|
|
'string' => $tmp_dest->fake_full_path,
|
|
'relatives' => $tmp_dest->mask
|
|
));
|
|
}
|
|
|
|
$this->mkdir(array(
|
|
'string' => $tmp_dest->fake_full_path,
|
|
'relatives' => array($tmp_dest->mask)
|
|
));
|
|
|
|
|
|
# see if user has add permission in destination folder
|
|
if (!$this->acl_check(array(
|
|
'string' => $dest->fake_full_path,
|
|
'relatives' => $dest->mask,
|
|
'operation' => PHPGW_ACL_ADD,
|
|
'must_exist' => true ))
|
|
)
|
|
{
|
|
return false; //TODO error handling
|
|
}
|
|
|
|
#extract files
|
|
switch ($data['type'])
|
|
{
|
|
case 'zip':
|
|
$zip =& CreateObject('phpgwapi.PclZip',$arch->real_full_path);
|
|
if (!$zip->extract(PCLZIP_OPT_PATH,$tmp_dest->real_full_path,PCLZIP_OPT_SET_CHMOD,DEFAULT_LOW_PERMS))
|
|
{
|
|
return false; //TODO handle error
|
|
}
|
|
break;
|
|
default:
|
|
return false;
|
|
/*
|
|
|
|
$archive_opts = array(
|
|
'basedir' => $tmp_dest->real_full_path,
|
|
'overwrite' => 1 //provisory, todo error handling
|
|
);
|
|
|
|
$compression_class = $compression_handlers[$data['type']].'_file';
|
|
$archive_obj = new $compression_class($arch->real_full_path);
|
|
$archive_obj->set_options($archive_opts);
|
|
$archive_obj->extract_files();
|
|
*/
|
|
|
|
/* $tar =& CreateObject('phpgwapi.Archive_Tar',$arch->real_full_path);
|
|
if (!$tar->extract($tmp_dest->real_full_path))
|
|
{
|
|
return false; //TODO handle error
|
|
}
|
|
break;*/
|
|
default:
|
|
return false; //TODO handle error
|
|
}
|
|
|
|
#refresh db
|
|
$filelist = $this->ls(array(
|
|
'string' => $tmp_dest->fake_full_path,
|
|
'relatives' => array($tmp_dest->mask),
|
|
'checksubdirs' => true,
|
|
'nofiles' => false
|
|
));
|
|
|
|
foreach ($filelist as $file)
|
|
{
|
|
$res = $this->mv(array(
|
|
'from' => $file['directory'].'/'.$file['name'],
|
|
'to' => $dest->fake_full_path.'/'.$file['name'],
|
|
'relatives' => array(RELATIVE_NONE|VFS_REAL,$dest->mask)
|
|
));
|
|
|
|
$this->set_attributes(array(
|
|
'string' => $dest->fake_full_path.'/'.$file['name'],
|
|
'relatives' => array($dest->mask),
|
|
'attributes' => array(
|
|
'prefix' => $data['prefix'],
|
|
'ptype' => $data['ptype'],
|
|
'mime_type' => $file['mime_type'],
|
|
'size' => $file['size']
|
|
)
|
|
));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*!
|
|
* @function random_filename()
|
|
* @abstract Generates a Random Filename
|
|
*
|
|
* @result string
|
|
*/
|
|
function random_filename()
|
|
{
|
|
$filename = '';
|
|
$filename_length = 8;
|
|
while (strlen($filename) < $filename_length) {
|
|
$filename .= chr(rand (97,122));
|
|
}
|
|
|
|
return $filename.'.tmp';
|
|
}
|
|
|
|
function generate_proper_id($owner_name,$filetype_identifier)
|
|
{
|
|
$prefix = $owner_name.'-'.$filetype_identifier.'-';
|
|
#$prefix = 'P-' . $this->year . '-';
|
|
|
|
$prefix = str_replace('--','-',$prefix);
|
|
|
|
$qry = "select max(proper_id) from phpgw_vfs2_files where proper_id like ('$prefix%') AND LENGTH(proper_id) <= ".(strlen($prefix)+4);
|
|
|
|
// echo $qry;
|
|
// exit();
|
|
|
|
$this->db->query("select max(proper_id) from phpgw_vfs2_files where proper_id like ('$prefix%') AND LENGTH(proper_id) <= ".(strlen($prefix)+4));
|
|
$this->db->next_record();
|
|
$max = $this->add_leading_zero(array_pop(explode('-',$this->db->f(0))));
|
|
return $prefix . $max;
|
|
}
|
|
|
|
function add_leading_zero($num)
|
|
{
|
|
/* if ($id_type == "hex")
|
|
{
|
|
$num = hexdec($num);
|
|
$num++;
|
|
$num = dechex($num);
|
|
}
|
|
else
|
|
{
|
|
$num++;
|
|
} */
|
|
|
|
$num++;
|
|
|
|
if (is_numeric($num))
|
|
{
|
|
if (strlen($num) == 4)
|
|
$return = $num;
|
|
if (strlen($num) == 3)
|
|
$return = "0$num";
|
|
if (strlen($num) == 2)
|
|
$return = "00$num";
|
|
if (strlen($num) == 1)
|
|
$return = "000$num";
|
|
if (strlen($num) == 0)
|
|
$return = "0001";
|
|
}
|
|
else
|
|
{
|
|
$return = $num;
|
|
}
|
|
|
|
return strtoupper($return);
|
|
}
|
|
|
|
|
|
//import function from old vfs
|
|
function import_vfs()
|
|
{
|
|
$filename = PHPGW_API_INC.'/class.vfs_sql.inc.php';
|
|
|
|
if (function_exists('file_get_contents'))
|
|
{
|
|
$file_vfs_sql = file_get_contents($filename);
|
|
}
|
|
else
|
|
{
|
|
$fp = fopen($filename,'r');
|
|
$file_vfs_sql = fread($fp,filesize($filename));
|
|
fclose($fp);
|
|
}
|
|
|
|
$file_vfs_sql = str_replace(
|
|
array('class vfs','function vfs','<?php','<?','?>'),
|
|
array('class vfs_sql_old','function vfs_sql_old'),$file_vfs_sql
|
|
);
|
|
|
|
eval($file_vfs_sql);
|
|
|
|
$obj_vfs_sql = new vfs_sql_old();
|
|
|
|
$obj_vfs_sql->override_acl = true;
|
|
|
|
$directories = $obj_vfs_sql->ls(array(
|
|
'string' => '/',
|
|
'relatives' => array(RELATIVE_ROOT),
|
|
'checksubdirs' => true,
|
|
'nofiles' => false,
|
|
'mime_type' => 'Directory'
|
|
));
|
|
|
|
$global_content = $obj_vfs_sql->ls(array(
|
|
'string' => '/',
|
|
'relatives' => array(RELATIVE_ROOT),
|
|
'checksubdirs' => true,
|
|
'nofiles' => false
|
|
));
|
|
|
|
$obj_vfs_sql->override_acl = false;
|
|
|
|
$this->override_acl = true;
|
|
|
|
foreach($directories as $key => $dir)
|
|
{
|
|
$dirname = str_replace('//','/',$dir['directory'].'/'.$dir['name']);
|
|
$dir_exists_in_vfs2 = $this->file_exists(array(
|
|
'string' => $dirname,
|
|
'relatives' => array(RELATIVE_ROOT),
|
|
'allow_outside' => false
|
|
));
|
|
|
|
|
|
if ($dir_exists_in_vfs2)
|
|
{
|
|
$dir_is_dir = $this->file_type(array(
|
|
'string' => $dirname,
|
|
'relatives' => array(RELATIVE_ROOT)
|
|
)) == 'Directory';
|
|
|
|
if ($dir_is_dir)
|
|
{
|
|
//good - just add permissions to the old owner
|
|
|
|
//1. get information about file
|
|
|
|
$file_info = $this->ls(array(
|
|
'string' => $dirname,
|
|
'relatives' => array(RELATIVE_ROOT),
|
|
'nofiles' => true,
|
|
'checksubdirs' => false,
|
|
'allow_outside' => false
|
|
));
|
|
|
|
if (!$file_info['proper_id'])
|
|
{
|
|
$this->set_attributes(array(
|
|
'string' => $dirname,
|
|
'relatives' => array(RELATIVE_ROOT),
|
|
'attributes' => array(
|
|
'prefix' => $GLOBALS['phpgw']->accounts->id2name($dir['owner_id']),
|
|
'comment' => $dir['comment']
|
|
)
|
|
));
|
|
}
|
|
|
|
//if user is not the owner of the file, will
|
|
//add him in the list of authorized personnel
|
|
if (array_key_exists(0,$file_info) && $file_info[0]['owner_id'] != $dir['owner_id'])
|
|
{
|
|
$file_id = $this->get_file_id(array(
|
|
'string' => $dirname,
|
|
'relatives' => array(RELATIVE_ROOT)
|
|
));
|
|
|
|
if ($file_id != 0)
|
|
{
|
|
if ($dirname != "/" && $dirname != "/home")
|
|
{
|
|
$perms = $this->vfs_sharing->get_permissions($file_id);
|
|
$perms[$dir['owner_id']] = PHPGW_ACL_READ | PHPGW_ACL_ADD | PHPGW_ACL_EDIT | PHPGW_ACL_DELETE;
|
|
|
|
$this->vfs_sharing->set_permissions(array($file_id => $perms));
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//something gone wrong... This should not have
|
|
//happened
|
|
trigger_error('Failed in permission setting of file <b>'.$dirname.'</b> at importing procedure.');
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
$this->mv(array(
|
|
'from' => $dirname,
|
|
'to' => $dirname.'_renamed',
|
|
'relatives' => array(RELATIVE_ROOT,RELATIVE_ROOT)
|
|
));
|
|
//error, bacuse wanting to touch a dir that is a
|
|
//file in new vfs
|
|
}
|
|
}
|
|
|
|
$this->mkdir(array(
|
|
'string' => $dirname,
|
|
'relatives' => array(RELATIVE_ROOT)
|
|
));
|
|
|
|
unset($dir['file_id']);
|
|
|
|
$dir['prefix'] = $GLOBALS['phpgw']->accounts->id2name($dir['owner_id']);
|
|
|
|
$this->set_attributes(array(
|
|
'string' => $dirname,
|
|
'relatives' => array(RELATIVE_ROOT),
|
|
'attributes' => $dir
|
|
));
|
|
}
|
|
|
|
foreach($global_content as $file)
|
|
{
|
|
$filename = str_replace('//','/',$file['directory'].'/'.$file['name']);
|
|
$file_exists_in_vfs2 = $this->file_exists(array(
|
|
'string' => $filename,
|
|
'relatives' => array(RELATIVE_ROOT),
|
|
'allow_outside' => false
|
|
));
|
|
|
|
|
|
if ($file['mime_type'] != 'Directory')
|
|
{
|
|
if ($file_exists_in_vfs2)
|
|
{
|
|
$file_is_dir = $this->file_type(array(
|
|
'string' => $filename,
|
|
'relatives' => array(RELATIVE_ROOT)
|
|
)) == 'Directory';
|
|
|
|
if (!$file_is_dir)
|
|
{
|
|
//good - just add permissions to the old owner
|
|
|
|
//1. get information about file
|
|
|
|
$file_info = $this->ls(array(
|
|
'string' => $filename,
|
|
'relatives' => array(RELATIVE_ROOT),
|
|
'nofiles' => true,
|
|
'checksubdirs' => false,
|
|
'allow_outside' => false
|
|
));
|
|
|
|
if (!$file_info['proper_id'])
|
|
{
|
|
$this->set_attributes(array(
|
|
'string' => $filename,
|
|
'relatives' => array(RELATIVE_ROOT),
|
|
'attributes' => array(
|
|
'prefix' => $GLOBALS['phpgw']->accounts->id2name($file['owner_id']),
|
|
'comment' => $file['comment']
|
|
)
|
|
));
|
|
}
|
|
|
|
//if user is not the owner of the file, will
|
|
//add him in the list of authorized personnel
|
|
if (array_key_exists(0,$file_info) && $file_info[0]['owner_id'] != $file['owner_id'])
|
|
{
|
|
$file_id = $this->get_file_id(array(
|
|
'string' => $filename,
|
|
'relatives' => array(RELATIVE_ROOT)
|
|
));
|
|
|
|
if ($file_id != 0)
|
|
{
|
|
if ($filename != "/" && $filename != "/home")
|
|
{
|
|
$perms = $this->vfs_sharing->get_permissions($file_id);
|
|
$perms[$file['owner_id']] = PHPGW_ACL_READ | PHPGW_ACL_ADD | PHPGW_ACL_EDIT | PHPGW_ACL_DELETE;
|
|
|
|
$this->vfs_sharing->set_permissions(array($file_id => $perms));
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//something gone wrong... This should not have
|
|
//happened
|
|
trigger_error('Failed in permission setting of file <b>'.$filename.'</b> at importing procedure.');
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
$this->mv(array(
|
|
'from' => $filename,
|
|
'to' => $filename.'_renamed',
|
|
'relatives' => array(RELATIVE_ROOT,RELATIVE_ROOT)
|
|
));
|
|
//error, bacuse wanting to touch a file that is a
|
|
//dir in new vfs
|
|
}
|
|
|
|
}
|
|
|
|
$this->touch(array(
|
|
'string' => $filename,
|
|
'relatives' => array(RELATIVE_ROOT)
|
|
));
|
|
|
|
unset($file['file_id']);
|
|
|
|
$file['prefix'] = $GLOBALS['phpgw']->accounts->id2name($file['owner_id']);
|
|
|
|
$this->set_attributes(array(
|
|
'string' => $filename,
|
|
'relatives' => array(RELATIVE_ROOT),
|
|
'attributes' => $file
|
|
|
|
));
|
|
|
|
}
|
|
}
|
|
$this->override_acl = false;
|
|
}
|
|
|
|
# #
|
|
# Functions that treat with application dirs #
|
|
# #
|
|
|
|
//gets the root of the application files dir
|
|
function get_appfiles_root()
|
|
{
|
|
if ($this->appfiles_root)
|
|
{
|
|
return $this->appfiles_root;
|
|
}
|
|
|
|
$appfiles_root = '/'.$GLOBALS['phpgw_info']['server']['file_appfolder'];
|
|
|
|
if ($appfiles_root == '/') //folder not set in setup
|
|
{
|
|
//see if there is a /infolog file in vfs. If have, use it. Else use /appfiles.
|
|
$res = $this->db->select('phpgw_vfs2_files','file_id',array('directory'=>'/','name'=>'infolog'),__LINE__,__FILE__);
|
|
if ($this->db->next_record()) //dir exists
|
|
{
|
|
$appfiles_root = '/infolog';
|
|
}
|
|
else
|
|
{
|
|
$appfiles_root = '/appfiles';
|
|
}
|
|
}
|
|
$this->appfiles_root = $appfiles_root;
|
|
return $appfiles_root;
|
|
}
|
|
|
|
//is folder belonging to an application (like for instance projects)
|
|
//$path is the virtual path. Pass the real path here seems nonsense now.
|
|
function is_appfolder($path)
|
|
{
|
|
$app_files_root = $this->get_appfiles_root();
|
|
|
|
return preg_match('/'.str_replace('/',"\\/",$app_files_root).'/',$path);
|
|
}
|
|
|
|
|
|
/**
|
|
* Method: get_external_name
|
|
*
|
|
* Given an application name and an id of this application,
|
|
* returns its name.
|
|
*/
|
|
function get_external_name($p_appname,$p_appid)
|
|
{
|
|
if (!$this->external_files_info)
|
|
{
|
|
$this->_consult_external_files_info();
|
|
}
|
|
|
|
if (!$this->external_files_info[$p_appname][$p_appid]['caption'])
|
|
{
|
|
return $GLOBALS['phpgw']->hooks->single(array(
|
|
'appname' => $p_appname,
|
|
'location' => 'get_name',
|
|
'id' => $p_appid
|
|
));
|
|
}
|
|
else
|
|
{
|
|
return $this->external_files_info[$p_appname][$p_appid]['caption'];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Method: get_external_files_info
|
|
*
|
|
* Returns all the external files info. This is good for some applications
|
|
* that need to show all the external files or all the external folders
|
|
*/
|
|
function &get_external_files_info()
|
|
{
|
|
if (!$this->external_files_info)
|
|
{
|
|
$this->_consult_external_files_info();
|
|
}
|
|
return $this->external_files_info;
|
|
}
|
|
|
|
/**
|
|
* Method: _consult_external_files_info
|
|
*
|
|
* Consults the external files info and store it in the vfs
|
|
* object attribute $this->external_files_info
|
|
*/
|
|
function _consult_external_files_info()
|
|
{
|
|
//Gets the application dirs that were set as shared, to include them
|
|
//also in the tree
|
|
$application_shared_files = $this->vfs_sharing->get_shares(array(
|
|
'only_dir' => $this->get_appfiles_root(),
|
|
'account_id' => $GLOBALS['phpgw_info']['user']['account_id']
|
|
));
|
|
|
|
foreach($application_shared_files as $shared_file)
|
|
{
|
|
$shared_file = ereg_replace($this->get_appfiles_root().'\/*','',$shared_file['directory'].'/'.$shared_file['name']);
|
|
$shared_file = ereg_replace('\/*$','',$shared_file);
|
|
$shared_file = explode('/',$shared_file);
|
|
|
|
$appname = $shared_file[0];
|
|
$appid = $shared_file[1];
|
|
|
|
$include_also[$appname][] = $appid;
|
|
}
|
|
|
|
$this->external_files_info = $GLOBALS['phpgw']->hooks->process(array(
|
|
'location' => 'files_info',
|
|
'account_id' => $this->userinfo['account_id'],
|
|
'include_also' => $include_also
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Method: set_sharing
|
|
*
|
|
* Sets the file sharing of ONE file to the given ACL
|
|
*
|
|
* Parameters:
|
|
*
|
|
* string - the full string describing the file
|
|
* relatives - the array of relativity
|
|
* permissions - an array with the user id as key, and the permissions
|
|
* (that are a boolean operation of PHPGW_ACLs) as value.
|
|
* If you want to apply a default permission to all users,
|
|
* use the 0 id as key
|
|
*/
|
|
function set_sharing($params)
|
|
{
|
|
//sets the file attibute to be 'shared=Y'
|
|
$this->set_attributes(array(
|
|
'string' => $params['string'],
|
|
'relatives' => $params['relatives'],
|
|
'attributes' => array('shared' => 'Y')
|
|
));
|
|
|
|
$file_id = $this->get_file_id(array(
|
|
'string' => $params['string'],
|
|
'relatives' => $params['relatives']
|
|
));
|
|
|
|
$this->vfs_sharing->set_permissions(array($file_id => $params['permissions']));
|
|
}
|
|
|
|
|
|
/**
|
|
* Method: unset_sharing
|
|
*
|
|
* Unsets all file sharing and ACL permissions for a file
|
|
*
|
|
* Parameters:
|
|
*
|
|
* string - the full string describing the file
|
|
* relatives - the array of relativity
|
|
*/
|
|
function unset_sharing($params)
|
|
{
|
|
$this->set_attributes(array(
|
|
'string' => $params['string'],
|
|
'relatives' => $params['relatives'],
|
|
'attributes' => array('shared' => 'N')
|
|
));
|
|
|
|
$file_id = $this->get_file_id(array(
|
|
'string' => $params['string'],
|
|
'relatives' => $params['relatives']
|
|
));
|
|
|
|
$this->vfs_sharing->remove_all_permissions($file_id);
|
|
}
|
|
}
|
|
?>
|