Classes for vfs sql implementation v2

Responsible developer: viniciuscb (Vinicius Cubas Brand)
This commit is contained in:
raphaelpereira 2004-10-27 23:34:21 +00:00
parent e69b1c0f96
commit 252075f37a
7 changed files with 6235 additions and 9 deletions

View File

@ -0,0 +1,276 @@
<?php
/***************************************************************************\
* eGroupWare - File Manager *
* http://www.egroupware.org *
* Written by: *
* - Vinicius Cubas Brand <viniciuscb@users.sourceforge.net> *
* sponsored by Thyamad - http://www.thyamad.com *
* ------------------------------------------------------------------------- *
* Description: Custom Field class handler for VFS (SQL implementation v2) *
* ------------------------------------------------------------------------- *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; either version 2 of the License, or (at your *
* option) any later version. *
\***************************************************************************/
class vfs_customfields
{
var $db;
function vfs_customfields()
{
$this->db = $GLOBALS['phpgw']->db;
}
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #
# Functions to associate customfields to a file #
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #
//$file_id: the id of the file
function & get_fields_by_fileid($file_id)
{
if (!is_numeric($file_id) || !(((int)$file_id)==$file_id))
return false;
$sql = "SELECT cf.customfield_name as name,
cfd.data as data
FROM phpgw_vfs2_customfields cf,
phpgw_vfs2_customfields_data cfd
WHERE cf.customfield_id = cfd.customfield_id
AND cf.customfield_active = 'Y'
AND cfd.file_id = $file_id";
$this->db->query($sql,__LINE__,__FILE__);
while($this->db->next_record())
{
$result[$this->db->Record['name']] = $this->db->Record['data'];
}
return $result;
}
//$data = array(file_id => array('field1'=> 'value', ....),
// file_id2 => array(...) ... )
// Store will do insert or update, depending if the field exists or
// not.
function store_fields($data)
{
if (!is_array($data))
return false;
$fields = $this->get_customfields('customfield_name');
foreach($data as $file_id => $file_data)
{
foreach($file_data as $name => $value)
{
//Column type does not exists
if (!array_key_exists($name,$fields))
{
//TODO ERROR HANDLING
continue;
}
$this->db->insert('phpgw_vfs2_customfields_data',
array('data' => $value),
array('file_id'=>$file_id,'customfield_id'=>$fields[$name]['customfield_id']),
__LINE__,__FILE__);
}
}
return true;
}
//$data = array('file_id' => array('field1','field2',...),
// 'fileid2' => ... )
function delete_fields($data)
{
$fields = $this->get_customfields('customfield_name');
foreach($data as $file_id => $file_fields)
{
foreach($file_fields as $column_name)
{
if (!array_key_exists($column_name,$fields))
{
//TODO ERROR HANDLING
continue;
}
$this->db->delete('phpgw_vfs2_customfields_data',
array('file_id' => $file_id,'customfield_id'=>$fields[$column_name]['customfield_id']),__LINE__,__FILE__);
}
}
}
/* Search the files that have $keyword in any field, or in the fields
specified in the array fields
@param $fields array('field1','fields2',...)*/
function search_files($keyword,$fields=null)
{
$where = '';
if ($fields)
{
$customfields = $this->get_customfields('customfield_name');
foreach ($fields as $field)
{
if ($customfields[$field])
{
$cf_ids[] = 'customfield_id='.$customfields[$field]['customfield_id'];
}
}
if ($cf_ids)
{
$where = implode(' OR ',$cf_ids);
$where = 'AND ('.$where.')';
}
}
$sql = "SELECT file_id
FROM phpgw_vfs2_customfields_data
WHERE data LIKE '%$keyword%'
$where";
$this->db->query($sql,__LINE__,__FILE__);
$res = array();
while($this->db->next_record())
{
$res[] = $this->db->Record['file_id'];
}
return $res;
}
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #
# Functions to manage custom field types #
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #
//Gets all custom field types, indexed by $indexedby.
//Example: array( 'customfieldname1' => array('customfield_id'=>x,'customfield_description'=>y,'type'=>z...)...)
//@param bool $activeonly If true, brings only active fields
function get_customfields($indexedby='customfield_name',$activeonly=true)
{
$where=($activeonly)?array('customfield_active'=>'Y'):array();
$this->db->select('phpgw_vfs2_customfields','*',$where,
__LINE__,__FILE__);
$result = array();
while($this->db->next_record())
{
$result[] = $this->db->Record;
}
if (!is_array($result[0]) || !array_key_exists($indexedby,$result[0]))
{
$indexedby = 'customfield_name';
}
$result2 = array();
foreach($result as $key => $val)
{
$result2[$val[$indexedby]] = $val;
}
return $result2;
}
//samething that $this->get_customfields, but returns an array in the
//format array('name' => 'description', 'name2'=>'desc2',...)
function get_attributes($activeonly=true)
{
$where=($activeonly)?array('customfield_active'=>'Y'):array();
$this->db->select('phpgw_vfs2_customfields','*',$where,
__LINE__,__FILE__);
while($this->db->next_record())
{
$result[] = $this->db->Record;
}
$result2 = array();
foreach($result as $key => $val)
{
$result2[$val['customfield_name']] = $val['customfield_description'];
}
return $result2;
}
//Add a new type of custom field
//$type can be of the same possible types for egw
function add_customfield($name,$description,$type,$precision='',$active='N')
{
$active = strtoupper($active);
$res = $this->db->insert('phpgw_vfs2_customfields',array(
'customfield_name' => $name,
'customfield_description' => $description,
'customfield_type' => $type,
'customfield_precision' => $precision,
'customfield_active' => $active ),
__LINE__,__FILE__);
if ($res)
{
return true;
}
return false;
}
//Update a customfield type (customfield_name, customfield_description, type, precision, active)
function update_customfield($customfield_id,$data)
{
if (!is_numeric($customfield_id) || !(((int)$customfield_id)==$customfield_id))
{
return false;
}
if ($data['customfield_active'])
{
$data['customfield_active'] = strtoupper($data['customfield_active']);
}
if ($this->db->update('phpgw_vfs2_customfields',$data,array('customfield_id'=>$customfield_id),__LINE__,__FILE__))
{
return true;
}
return false;
}
//generally better inactivate a field than remove.
function remove_customfield($customfield_id)
{
$res = $this->db->delete('phpgw_vfs2_customfields',array('customfield_id'=>$customfield_id),__LINE__,__FILE__);
if ($res)
{
$res2 = $this->db->delete('phpgw_vfs2_customfields_data',array('customfield_id'=>$customfield_id),__LINE__,__FILE__);
if ($res2)
{
return true;
}
}
return false;
}
}
?>

View File

@ -0,0 +1,334 @@
<?php
/***************************************************************************\
* eGroupWare - File Manager *
* http://www.egroupware.org *
* Written by: *
* - Vinicius Cubas Brand <viniciuscb@users.sourceforge.net> *
* sponsored by Thyamad - http://www.thyamad.com *
* ------------------------------------------------------------------------- *
* Description: Mime type class handler for VFS (SQL implementation v2) *
* ------------------------------------------------------------------------- *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; either version 2 of the License, or (at your *
* option) any later version. *
\***************************************************************************/
#based on the filetypes.inc.php class by intermesh, see groupoffice.com
#02 Sep 2004 viniciuscb Initial Release
class vfs_mimetypes
{
var $default_filetype_icon;
var $db;
var $vfs; //Just to get mime types from vfs->get_ext_mime_type()
var $default_mimetype = "application/OCTET-STREAM";
function vfs_mimetypes($create_vfs=true)
{
//use create_vfs=false and after this use $this->set_vfs to keep the
// same object (i.e. use reference) in $this->vfs
if ($create_vfs)
{
$this->vfs = CreateObject('phpgwapi.vfs');
}
$this->default_filetype_icon = PHPGW_INCLUDE_ROOT.'/filescenter/icons/default.gif';
$this->db = $GLOBALS['phpgw']->db;
}
/*!
* function add_filetype
* @description Adds a new mime_type to the mime_types repository
* @note One of the two: extension or mime are required
* @param extension string A file extension
* @param mime string the mime type according to the RFCs 2046/1524
* @param friendly string File type description in human-friendly
* format
* @param image string content of icon file
* @param icon_name string complete path filename of icon image
* (note: will be used only when icon_data is not set)
* @param mime_magic data used for mime_magic functions (planned)
* @param return_image bool if true will return the binary data of image
* @result Array with mime_id and other mime info, false otherwise
*/
function add_filetype($data,$return_image=false,$dont_update=false)
{
if (!$data['extension'] && !$data['mime'])
{
return false;
}
if (!$data['mime'])
{
$data['mime'] = $this->get_mime_type($data['extension']);
}
elseif (!$data['extension'])
{
$data['extension'] = '(n/a)'; //Thinking in 'Directory'
}
if (!$data['friendly'])
{
if ($data['extension'] != '(n/a)')
{
$data['friendly'] = strtoupper($data['extension']).' File';
}
else
{
$data['friendly'] = $data['mime'];
}
}
if (!$data['image'])
{
if (!$data['icon_name'] || !file_exists($data['icon_name']))
{
$data['icon_name'] = $this->default_filetype_icon;
}
$fp = fopen($data['icon_name'],"r");
$data['image'] = fread($fp,filesize($data['icon_name']));
fclose($fp);
unset($data['icon_name']);
}
$where['extension'] = $data['extension'];
#$where['mime'] = $data['mime'];
if ($dont_update)
{
$this->db->select('phpgw_vfs2_mimetypes','mime_id',$where,__LINE__,__FILE__);
if ($this->db->next_record())
{
return false; //msgerror Existent register that cannot be overwritten
}
}
$res = $this->db->insert('phpgw_vfs2_mimetypes',$data,$where,__LINE__,__FILE__);
if($res)
{
$this->db->select('phpgw_vfs2_mimetypes','mime_id',$where,
__LINE__,__FILE__);
$this->db->next_record();
$data['mime_id'] = $this->db->Record['mime_id'];
if (!$return_image)
{
unset($data['image']);
}
return $data;
}
return false;
}
/*!
* function edit_filetype
* @description Edits a mime_type of the mime_types repository
* @note mime_id required. Will change only passed vars.
* @param extension string A file extension
* @param mime string the mime type according to the RFCs 2046/1524
* @param friendly string File type description in human-friendly
* format
* @param image string content of icon file
* @param icon_name string complete path filename of icon image
* (note: will be used only when icon_data is not set)
* @param mime_magic data used for mime_magic functions (planned)
* @param return_image bool if true will return the binary data of image
* @result Array with mime_id and other mime info, false otherwise
*/
function edit_filetype($data,$return_image=false)
{
if (!$data['mime_id'])
{
return false;
}
$where['mime_id'] = $data['mime_id'];
$res = $this->db->update('phpgw_vfs2_mimetypes',$data,$where,__LINE__,__FILE__);
if($res)
{
if ($return_image)
{
$return_fields = '*';
}
else
{
$return_fields = 'mime_id,extension,mime,friendly,mime_magic,proper_id';
}
$this->db->select('phpgw_vfs2_mimetypes',$return_fields,$where,
__LINE__,__FILE__);
$this->db->next_record();
return $this->db->Record;
}
return false;
}
/*!
* function get_type
* @description Returns a mime type, based in extension or mime_id
* @param $desc array have index 'extension', 'mime_id' or 'mime'
* @param $return_image if true will return the binary data of image
* @result Array with mime_id and other mime info, false otherwise
*/
function get_type($data, $return_image=false)
{
//TODO error messages
if ((!$data['extension'] || $data['extension'] == '(n/a)') &&
!$data['mime_id'] && !$data['mime'])
return false;
$return_fields = ($return_image)?'*':'mime_id,extension,friendly,mime_magic,mime,proper_id';
if ($data['mime_id'])
{
$this->db->select('phpgw_vfs2_mimetypes',$return_fields,
array('mime_id'=>$data['mime_id']),__LINE__,__FILE__);
}
else if ($data['extension'])
{
$this->db->select('phpgw_vfs2_mimetypes',$return_fields,
array('extension'=>$data['extension']),__LINE__,__FILE__);
}
else if ($data['mime'])
{
$this->db->select('phpgw_vfs2_mimetypes',$return_fields,
array('mime'=>$data['mime']),__LINE__,__FILE__);
}
if($this->db->next_record())
return $this->db->Record;
return false;
}
/*!
* function get_filetypes
* @description Returns an array with all file types in the repository
* @param $return_images if true, the images are returned in the array
* @param $offset int if specified, will bring a subset of repository
* @result Array: $arr[1]['mime_id'] ...
*/
function get_filetypes($return_images=false,$offset=false)
{
$return_fields = ($return_images)?'*':'mime_id,extension,friendly,mime_magic,mime,proper_id';
$this->db->select('phpgw_vfs2_mimetypes',$return_fields,false,
__LINE__,__FILE__,$offset);
$result = array();
while ($this->db->next_record())
{
$result[] = $this->db->Record;
}
return $result;
}
/*!
* function update_filetype
* @description Updates a file type information in the filetype
* repository
* @param $return_image if true will return the binary data of image
* @note parameters in $data: the same of add_filetype()
* @result bool true on success, false otherwise
*/
function update_filetype($data)
{
if (!$data['mime_id'])
{
return false;
}
if ($data['icon_name'])
{
if (file_exists($data['icon_name']))
{
$fp = fopen($data['icon_name'],"r");
$data['image'] = fread($fp,filesize($icon));
fclose($fp);
}
unset($data['icon_name']);
}
$where['mime_id'] = $data['mime_id'];
if ($this->db->update('phpgw_vfs2_mimetypes',$data,$where,__LINE__,
__FILE__))
return true;
return false;
}
/*!
* function delete_filetype
* @description deletes a type from the file type repository
* @param $mime_id the mime_id of the record
* @result bool true on success, false otherwise
*/
function delete_filetype($mime_id)
{
if ($this->db->delete('phpgw_vfs2_mimetypes',
array('mime_id'=>$mime_id),__LINE__,__FILE__))
return true;
return false;
}
function set_vfs(&$vfs)
{
$this->vfs =& $vfs;
}
#private methods
function get_mime_type($extension)
{
return $this->vfs->get_ext_mime_type(array('string'=>$extension));
}
function default_values ($data, $default_values)
{
for ($i = 0; list ($key, $value) = each ($default_values); $i++)
{
if (!isset ($data[$key]))
{
$data[$key] = $value;
}
}
return $data;
}
}
?>

View File

@ -0,0 +1,373 @@
<?php
/***************************************************************************\
* eGroupWare - File Manager *
* http://www.egroupware.org *
* Written by: *
* - Vinicius Cubas Brand <viniciuscb@users.sourceforge.net> *
* sponsored by Thyamad - http://www.thyamad.com *
* ------------------------------------------------------------------------- *
* Description: File ID Prefixes class handler for SQL implementation v2 *
* ------------------------------------------------------------------------- *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; either version 2 of the License, or (at your *
* option) any later version. *
\***************************************************************************/
#12 Oct 2004 viniciuscb Initial Release
define ('PHPGW_VFS2_PREFIX_APP','vfs2_prefix'); //for prefix
define ('PHPGW_VFS2_PTYPE_APP','vfs2_ptype'); //for file type
class vfs_prefixes
{
var $db;
var $table_fields = array(
'prefix_id',
'owner_id',
'prefix',
'prefix_description',
'prefix_type'
);
function vfs_prefixes()
{
$this->db = $GLOBALS['phpgw']->db;
}
/*!
* function add
* @description Adds a new File ID Prefix to the prefixes repository
* @param prefix string (required) A prefix
* @param prefix_description string (optional) Brief prefix description
* @param owner_id int (required) Owner Id of prefix
* @param prefix_type (optional) can be 'p' for prefix, 't' for type.
* @result (int) prefix_id
*
* @note: will search for another equal $prefix in repository. If
* exists, returns its prefix_id and if user have permission,
* updates this prefix. If don't exists, insert and return its
* prefix_id. $dont_update will not do any update if exists, even
* if current user can update.
*/
function add($data,$dont_update=false)
{
if (!$data['prefix'])
{
return false;
}
if (!$data['prefix_type'])
{
$data['prefix_type'] = 'p';
}
//eliminate keys which are not a field in table
foreach($data as $key => $val)
{
if (!in_array($key,$this->table_fields))
{
unset($data[$key]);
}
}
//see if exists some equal prefix id
$this->db->select('phpgw_vfs2_prefixes','prefix_id',array('prefix' => $data['prefix']));
if($this->db->next_record()) //exists
{
if ($dont_update)
{
return $this->db->Record['prefix_id'];
}
$data['prefix_id'] = $this->db->Record['prefix_id'];
return $this->edit($data);
}
if (!$data['owner_id'])
{
$data['owner_id'] = $GLOBALS['phpgw_info']['user']['account_id'];
}
$this->db->insert('phpgw_vfs2_prefixes',$data,false,__LINE__,__FILE__);
$this->db->select('phpgw_vfs2_prefixes','prefix_id',array('prefix' => $data['prefix']));
if($this->db->next_record()) //exists
{
return $this->db->Record['prefix_id'];
}
return false;
}
/*!
* function edit
* @description Edits a File ID Prefix
* @param prefix_id int (required) The ID for prefix
* @param prefix string (optional) A prefix
* @param prefix_description string (optional) Brief prefix description
* @param owner_id int (optional) Owner Id of prefix
* @param prefix_type (optional) can be 'p' for prefix, 't' for type.
* @result (int) prefix_id
* @result (bool) true on success, false on any other possibility
*/
function edit($data)
{
if (!$data['prefix_id'])
{
return false;
}
//eliminate keys which are not a field in table
foreach($data as $key => $val)
{
if (!in_array($key,$this->table_fields))
{
unset($data[$key]);
}
}
$where['prefix_id'] = $data['prefix_id'];
unset($data['prefix_id']);
return $this->db->update('phpgw_vfs2_prefixes',$data,$where,__LINE__,__FILE__);
}
/*!
* function remove
* @description Removes a File ID Prefix
* @param prefix_id int (required) The ID for prefix
* @result (bool) true on success, false on any other possibility
*/
function remove($prefix_id)
{
return $this->db->delete('phpgw_vfs2_prefixes',array('prefix_id' => $prefix_id),__LINE__,__FILE__);
}
/*!
* function get
* @description Gets information about a prefix just based in prefix_id
* @param prefix_id int (required) The ID for prefix
* OR
* @param prefix int (required) The prefix
* @result (array) with column names as indexes, empty array if inexist
*/
function get($data)
{
if (!$data['prefix_id'] && !$data['prefix'])
return false;
$this->db->select('phpgw_vfs2_prefixes','*',$data,__LINE__,__FILE__);
if ($this->db->next_record())
{
return $this->db->Record;
}
return array();
}
/*!
* function get_prefixes
* @description Gets all prefixes this user can view, based in querying
* acl
* @param user_id int (required) The ID of user to whom you want to
* know, or will get current user as default
* @param status string If 'view', returns info about all prefixes
* user can view. if 'owns', return only prefixes user owns
* @result (array) with column names as indexes, empty array if inexist
*/
function get_prefixes($status='view',$user_id=false,$type='p')
{
if (!$user_id)
{
$user_id = $GLOBALS['phpgw_info']['user']['account_id'];
}
switch ($status)
{
case 'owns':
$this->db->select('phpgw_vfs2_prefixes','*',array('owner_id'=>$user_id,'prefix_type'=>$type),__LINE__,__FILE__);
while($this->db->next_record())
{
$return[] = $this->db->Record;
}
break;
case 'view':
$acl = CreateObject('phpgwapi.acl',$user_id);
//fetch ids of prefixes that user can view
if (!$pr_list = $acl->get_location_list_for_id(PHPGW_VFS2_PREFIX_APP,PHPGW_ACL_READ,$user_id))
{
$pr_list = array();
}
//fetch ids of prefixes that groups user belong to can view
//Note: this will be in two phases. One: fetch groups user
// belongs to. Two: fetch prefix list for these groups
/* Note: prefixes are organized in phpgwapi.acl in the
* following schema:
* - appname: (PHPGW_VFS2_PREFIX_APP)
* - location: id_prefix
* - account_id: Id of user that has grants (not the
* grantor. The grantor is only the owner of prefix,
* defined in prefixes repository).
* - acl_rights: PHPGW_ACL_READ
*/
$user_groups = $GLOBALS['phpgw']->accounts->membership($user_id);
foreach($user_groups as $group)
{
if (!$group_pr_list = $acl->get_location_list_for_id(PHPGW_VFS2_PREFIX_APP,PHPGW_ACL_READ,$group['account_id']))
{
$group_pr_list = array();
}
$pr_list = array_merge($pr_list,$group_pr_list);
}
//remove dupliate values
$pr_list = array_unique($pr_list);
//now we have the list of prefixes user can view. We must
//now fetch complete information about prefixes of
//phpgw_vfs2_prefixes
if (!count($pr_list))
{
return array();
}
if ($pr_list)
{
$prefix_string = '('.implode(',',$pr_list).')';
$this->db->select('phpgw_vfs2_prefixes','*','prefix_id IN '.$prefix_string." AND prefix_type='$type'",__LINE__,__FILE__);
while($this->db->next_record())
{
$return[] = $this->db->Record;
}
}
else
{
return array();
}
break;
default:
return false;
}
return $return;
}
/*!
* function update_permissions
* @description Updates users who can see a prefix
*
* @param prefix_id int (required) The prefix that will have permissions
* changed
* @param user_list array Array with account_ids that can read prefix
* as values.
*
* @result (bool)
*/
function update_permissions($prefix_id,$user_list)
{
//1. see if current user is owner of the prefix
$current_user_id = $GLOBALS['phpgw_info']['user']['account_id'];
$prefix_info = $this->get(array('prefix_id'=>$prefix_id));
if ($current_user_id != $prefix_info['owner_id'])
{
return false;
}
//2. get current permission for prefix
$current_permissions = $this->get_permissions(array('prefix_id'=>$prefix_id));
//3. change permissions
$list_of_users_to_add = array_diff($user_list,$current_permissions);
$list_of_users_to_del = array_diff($current_permissions,$user_list);
$acl = CreateObject('phpgwapi.acl',$current_user_id);
foreach($list_of_users_to_add as $user_id)
{
$acl->account_id = $user_id;
$acl->read_repository();
#echo "<br>\nAdded: prefix $prefix_id ; user $user_id";
$acl->add(PHPGW_VFS2_PREFIX_APP,$prefix_id,PHPGW_ACL_READ);
$acl->save_repository();
}
foreach($list_of_users_to_del as $user_id)
{
$acl->account_id = $user_id;
$acl->read_repository();
#echo "<br>\nDeleted: prefix $prefix_id ; user $user_id";
$acl->delete(PHPGW_VFS2_PREFIX_APP,$prefix_id);
$acl->save_repository();
}
}
/*!
* function get_permissions
* @description This will get all permissions for a given prefix.
* In other words, will return an array of all accounts who
* can see a prefix. Will not dive into groups' users,
* only showing user and group accounts who can see
* prefix.
*
* @param prefix int (required) The File ID Prefix
* OR
* @param prefix_id int (required) The ID of the File ID Prefix
* @param prefixes array The same type of the return of get_prefixes
*
* @result (array) with column names as indexes, empty array if inexist
*/
function get_permissions($data)
{
if (is_numeric($data))
{
$prefix_id = $data;
}
elseif ($data['prefix'])
{
$this->db->select('phpgw_vfs2_prefixes','prefix_id',array('prefix'=>$data['prefix']),__LINE__,__FILE__);
if ($this->db->next_record())
{
$prefix_id = $this->db->Record['prefix_id'];
}
}
elseif($data['prefix_id'])
{
$prefix_id = $data['prefix_id'];
}
if (!$prefix_id)
{
return false;
}
$acl = CreateObject('phpgwapi.acl');
$user_ids = $acl->get_ids_for_location($prefix_id,PHPGW_ACL_READ,PHPGW_VFS2_PREFIX_APP);
return ($user_ids)?$user_ids:array();
}
}
?>

View File

@ -492,6 +492,10 @@
*
* update_real - Ensure that information about a location is
* up-to-date
*
* compress - Archives a file or set of files in a compressed file
*
* extract - Dearchives a file or set of files of a compressed file
*/
/*!
@ -507,6 +511,37 @@
* @result Boolean. True on success, False otherwise.
*/
function update_real ($data) { return False; }
/*!
* @function compress
* @abstract Creates an archive from a file or a set of files
* @required files File names to be stored in archive (array)
* @required name Name of archive
* @optional type The type of compression, can be 'zip'(default)or 'gz'
* @optional relatives Relativity array (default: RELATIVE_CURRENT)
* Note: the last item is the relativity of the dest archive
* @result Boolean. True on success, False otherwise.
*/
function compress ($data) { return False; }
/*!
* @function extract
* @abstract Extracts a file (or files) from archive
* @required name Name of archive
* @required dest The destination path of files to be extracted
* @optional type The type of compression, can be 'zip' or 'gz'. If
* not specified, uses according to the extension
* @optional files Files to be extracted from archive
* @optional relatives Relativity array (default: RELATIVE_CURRENT)
* Note: the first item is the relativity of the archive, the last of
* the dest dir
* @result Boolean. True on success, False otherwise.
*/
function extract ($data) { return False; }
/*
* SHARED FUNCTIONS
@ -526,6 +561,12 @@
* sanitize - Remove any possible security problems from a location
* string (i.e. remove leading '..')
*
* clean_string - Clean location string. This function is used if
* any special characters need to be escaped or removed
* before accessing a database, network protocol, etc.
* The default is to escape characters before doing an SQL
* query.
*
* getabsolutepath - Translate a location string depending on the
* relativity. This is the only function that is
* directly concerned with relativity.
@ -543,7 +584,7 @@
*
* cd - Change current directory. This function is used to store the
* current directory in a standard way, so that it may be accessed
* throughout eGroupWare to provide a consistent view for the user.
* throughout phpGroupWare to provide a consistent view for the user.
*
* pwd - Return current directory
*
@ -556,6 +597,10 @@
* dir - Alias for ls
*
* command_line - Process and run a Unix-sytle command line
*
* compress - Archives a file or set of files in a compressed file
*
* extract - Dearchives a file or set of files of a compressed file
*/
/* PRIVATE functions */
@ -613,6 +658,28 @@
return (ereg_replace ("^\.+", '', $p->fake_name));
}
/*!
* @function clean_string
* @abstract Clean location string. This function is used if
* any special characters need to be escaped or removed
* before accessing a database, network protocol, etc.
* The default is to escape characters before doing an SQL
* query.
* @required string Location string to clean
* @result String. Cleaned version of 'string'.
*/
function clean_string ($data)
{
if (!is_array ($data))
{
$data = array ();
}
$string = $GLOBALS['phpgw']->db->db_addslashes ($data['string']);
return $string;
}
/*!
* @function getabsolutepath
* @abstract Translate a location string depending on the
@ -847,6 +914,18 @@
* real_leading_dirs
* real_extra_path BROKEN
* real_name
* fake_full_path_clean
* fake_leading_dirs_clean
* fake_extra_path_clean BROKEN
* fake_name_clean
* real_full_path_clean
* real_leading_dirs_clean
* real_extra_path_clean BROKEN
* real_name_clean
* "clean" values are run through vfs->clean_string () and
* are safe for use in SQL queries that use key='value'
* They should be used ONLY for SQL queries, so are used
* mostly internally
* mask is either RELATIVE_NONE or RELATIVE_NONE|VFS_REAL,
* and is used internally
* outside is boolean, True if 'relatives' contains VFS_REAL
@ -999,6 +1078,28 @@
}
}
/*
We have to count it before because new keys will be added,
which would create an endless loop
*/
$count = count ($rarray);
reset ($rarray);
for ($i = 0; (list ($key, $value) = each ($rarray)) && $i != $count; $i++)
{
$rarray[$key . '_clean'] = $this->clean_string (array ('string' => $value));
}
if ($data['object'])
{
$robject = new path_class;
reset ($rarray);
while (list ($key, $value) = each ($rarray))
{
$robject->$key = $value;
}
}
/*
echo "<br>fake_full_path: $rarray[fake_full_path]
<br>fake_leading_dirs: $rarray[fake_leading_dirs]
@ -1012,22 +1113,19 @@
if ($data['object'])
{
$robject = new path_class;
foreach($rarray as $key => $value)
{
$robject->$key = $value;
}
return ($robject);
}
return ($rarray);
else
{
return ($rarray);
}
}
/*!
* @function cd
* @abstract Change current directory. This function is used to store the
* current directory in a standard way, so that it may be accessed
* throughout eGroupWare to provide a consistent view for the user.
* throughout phpGroupWare to provide a consistent view for the user.
* @discussion To cd to the root '/', use:
* cd (array(
* 'string' => '/',
@ -1306,6 +1404,7 @@
return $data;
}
}
?>

View File

@ -0,0 +1,424 @@
<?php
/***************************************************************************\
* eGroupWare - File Manager *
* http://www.egroupware.org *
* Written by: *
* - Vinicius Cubas Brand <viniciuscb@users.sourceforge.net> *
* sponsored by Thyamad - http://www.thyamad.com *
* ------------------------------------------------------------------------- *
* Description: File Sharing class handler for VFS (SQL implementation v2) *
* ------------------------------------------------------------------------- *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; either version 2 of the License, or (at your *
* option) any later version. *
\***************************************************************************/
// This class had to be created because file sharing work very differently
// In fm2 than in fm.
#FIXME this class is completely vfs_sql2 oriented. Must exist implementation
# to other types
class vfs_sharing
{
var $accounts;
var $db;
/*!
* function vfs_sharing
* @description Class constructor
*/
function vfs_sharing()
{
$this->accounts =& $GLOBALS['phpgw']->accounts;
$this->db = $GLOBALS['phpgw']->db;
}
/*!
* function set_permissions
* @description Add specified permissions that do not exist, remove
* unspecified permissions that exist. Easier to call than
* add_permissions and then remove_permissions
* @param array $data in the following format:
* array(
* file_id => array(
* account_id => acl_rights,
* account_id2 => acl_rights2,...
* ),
* file_id2 ... );
*/
function set_permissions($data)
{
//TODO see if a user have permissions in a file. Only if he have
//(or if is inside his homedir) he can change permissions
if (!$data || !is_array($data))
{
return false;
}
//search for permissions on files, to know which ones must be
//updated/inserted
reset($data);
while(list($file_id,$account_ids) = each($data))
{
$file_ids[] = $file_id;
}
$sql = 'SELECT * from phpgw_vfs2_shares
WHERE file_id IN ('.implode(',',$file_ids).')';
$this->db->query($sql,__LINE__,__FILE__);
while ($this->db->next_record())
{
$current_shares[$this->db->Record['file_id']][$this->db->Record['account_id']] = $this->db->Record['acl_rights'];
}
//now that we have the current permissions, must know which ones to
//insert/update and which ones to delete
reset($data);
while(list($file_id,$account_ids) = each($data))
{
reset($account_ids);
while(list($account_id,$acl_rights) = each($account_ids))
{
//exists
if (array_key_exists($account_id,$current_shares[$file_id]))
{
if ($current_shares[$file_id][$account_id] != $acl_rights)
{
$insert[$file_id][$account_id] = $acl_rights;
}
unset($current_shares[$file_id][$account_id]);
}
else
{
$insert[$file_id][$account_id] = $acl_rights;
}
}
}
//get which ones to delete
reset($current_shares);
while(list($file_id,$account_ids) = each($current_shares))
{
if (is_array($account_ids))
{
reset($account_ids);
while(list($account_id,$acl_rights) = each($account_ids))
{
$delete[$file_id][$account_id] = $acl_rights;
}
}
}
foreach($insert as $file_id => $account_ids)
{
$this->store_permissions($file_id,$account_ids);
}
foreach($delete as $file_id => $account_ids)
{
$this->remove_permissions($file_id,$account_ids);
}
return true;
}
/*!
* function store_qpermissions
* @description Add/update new permissions to a file id
* @param account_ids: array('account_id'=> acl_rights,acc_id2=>acl_r2,)
*/
function store_permissions($file_id,$account_ids)
{
if (!is_array($account_ids) || !is_numeric($file_id))
{
return false;
}
foreach($account_ids as $account_id => $acl_rights)
{
$this->db->insert('phpgw_vfs2_shares',
array('acl_rights'=>$acl_rights),
array('account_id'=>$account_id,'file_id'=>$file_id),
__LINE__,__FILE__);
}
return true;
}
/*!
* function remove_permissions
* @description Remove some permissions of a file id
*/
function remove_permissions($file_id,$account_ids)
{
if (!is_array($account_ids) || !is_numeric($file_id))
{
return false;
}
foreach($account_ids as $account_id => $acl_rights)
{
$this->db->delete('phpgw_vfs2_shares',
array('account_id'=>$account_id,'file_id'=>$file_id),
__LINE__,__FILE__);
}
return true;
}
/*!
* function get_permissions
* @description This function will get the permissions set for a given
* file, makeing a simple query in the file repository. Does not
* search for permissions in parent dirs. If you want to know which
* is the permission for a user in a given file TAKING IN COUNT the
* parent dirs, use $this->get_file_permissions instead.
* @param int file_id The id of the file
* @result array with account_id as index, acl_rights as value
* @author Vinicius Cubas Brand
*/
function get_permissions($file_id)
{
$this->db->select('phpgw_vfs2_shares','acl_rights,account_id',
array('file_id'=>$file_id),__LINE__,__FILE__);
$result = array();
while ($this->db->next_record())
{
$result[$this->db->Record['account_id']] = $this->db->Record['acl_rights'];
}
return ($result);
}
/*!
* function get_shares
* @description Get all shares in which the user have $permission
* @param $account_id The id of the user that can read the shared folder
* @param $is_owner If true, will get only the shared folders that
* $account_id owns. Useful to get the shares that account_id owns
* and have configured himself (true), or instead the shares of the
* others that he have $permission (false)
* @result array with the list of the file_id's of all shares
*/
function get_shares($account_id,$is_owner=false,$permission=PHPGW_ACL_READ)
{
if ($is_owner)
{
$sql = "SELECT DISTINCT sh.file_id as file_id,
sh.acl_rights as acl_rights,
fls.directory as directory,
fls.name as name
FROM phpgw_vfs2_shares sh,
phpgw_vfs2_files fls
WHERE sh.file_id = fls.file_id
AND fls.shared = 'Y'
AND fls.owner_id = $account_id";
}
else
{
//gets the id of all groups $account_id belongs to
$groups = $GLOBALS['phpgw']->accounts->membership($account_id);
foreach($groups as $group)
{
$accounts[] = $group['account_id'];
}
$accounts[] = $account_id;
$sql = "SELECT DISTINCT sh.file_id as file_id,
sh.acl_rights as acl_rights,
fls.directory as directory,
fls.name as name
FROM phpgw_vfs2_shares sh,
phpgw_vfs2_files fls
WHERE sh.file_id = fls.file_id
AND sh.account_id IN (".implode(',',$accounts).")
AND fls.shared = 'Y'
AND fls.owner_id != $account_id";
}
$this->db->query($sql,__LINE__,__FILE__);
$res = array();
while($this->db->next_record())
{
if($this->db->Record['acl_rights'] & $permission)
{
$res[] = $this->db->Record;
}
}
//should be returned the array with complete file description
return $res;
}
/*!
* function search_shares
* @description Search for a shared folder which the user have
* $permission and have $keyword related (in directory or filename)
* @result array with the list of all shares
*/
//TODO search by file owner's name
function search_shares($account_id,$keyword,$permission=PHPGW_ACL_READ)
{
if ($account_id != ((int)$account_id))
{
return false;
}
//gets the id of all groups $account_id belongs to
$groups = $GLOBALS['phpgw']->accounts->membership($account_id);
foreach($groups as $group)
{
$accounts[] = $group['account_id'];
}
$accounts[] = $account_id;
$sql = "SELECT DISTINCT sh.file_id as file_id,
sh.acl_rights as acl_rights,
fls.directory as directory,
fls.name as name
FROM phpgw_vfs2_shares sh,
phpgw_vfs2_files fls
WHERE sh.file_id = fls.file_id
AND sh.account_id IN (".implode(',',$accounts).")
AND ( fls.directory LIKE '%$keyword%'
OR fls.name LIKE '%$keyword%')
AND fls.shared = 'Y'
AND fls.owner_id != $account_id";
$this->db->query($sql,__LINE__,__FILE__);
while($this->db->next_record())
{
if ($this->db->Record['acl_rights'] & $permission)
{
$res[] = $this->db->Record;
}
}
return $res;
}
/*!
* function get_file_permissions
* @description Get the permissions for a user in a given file
* For files in a shared dir, will get the acl rights of the parent
* dir, and if not specified, of the parent of the parent, and so on.
* NOTE: this consider that files CANNOT have permissions set, only
* their parent dir, and the file inherits the nearer parent with
* permissions defined
* @result int some mask of various PHPGW_ACL_*
*/
function get_file_permissions($account_id,$file_id)
{
//get directory/file names
$this->db->select('phpgw_vfs2_files','directory,name',
array('file_id' => $file_id),__LINE__,__FILE__);
$this->db->next_record();
$directory = $this->db->Record['directory'];
$name = $this->db->Record['name'];
$fullname = $directory.'/'.$name;
$parent_dirs = array();
$dirs_expl = explode('/',$fullname);
//put all parents hierarchy in an array
$parent_dirs_array[]=$fullname;
while(1)
{
array_pop($dirs_expl);
if($dirs_expl[1])
{
$parent_dirs_array[]=implode('/',$dirs_expl);
}
else
{
$parent_dirs_array[]='/';
break;
}
}
//gets the id of all groups $account_id belongs to
$groups = $GLOBALS['phpgw']->accounts->membership($account_id);
foreach($groups as $group)
{
$accounts[] = $group['account_id'];
}
$accounts[] = $account_id;
$accounts = implode(',',$accounts);
//searches for information in the parent dirs
for($i=0; $i<count($parent_dirs_array);$i++)
{
$dir_name = array_pop(explode('/',$parent_dirs_array[$i]));
if ($dir_name)
{
$sql = "SELECT sh.acl_rights as acl_rights,
fls.directory as directory,
fls.name as name,
fls.owner_id as owner_id
FROM phpgw_vfs2_shares sh,
phpgw_vfs2_files fls
WHERE sh.file_id = fls.file_id
AND (sh.account_id IN ($accounts)
OR fls.owner_id = $account_id)
AND fls.directory = '".$parent_dirs_array[$i+1]."'
AND fls.name = '".$dir_name."'";
$this->db->query($sql,__LINE__,__FILE__);
/*
$this->db->select('phpgw_vfs2_files','file_id',
array('directory'=>$parent_dirs_array[$i+1],
'name'=>$dir_name), __LINE__,__FILE__);
$this->db->next_record();
$this->db->select('phpgw_vfs2_shares','acl_rights',
array('file_id'=>$this->db->Record['file_id'],
'account_id'=>$account_id),__LINE__,__FILE__);*/
while ($this->db->next_record())
{
if ($this->db->Record['owner_id'] == $account_id)
{
//the user can do anything with any dir or file
//inside a dir that belongs to him.
return PHPGW_ACL_READ|PHPGW_ACL_EDIT|PHPGW_ACL_ADD;
}
else
{
$entered = true;
$result |= $this->db->Record['acl_rights'];
}
}
if($entered)
{
return $result;
}
}
}
return false;
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,674 @@
<?php
/***************************************************************************\
* eGroupWare - File Manager *
* http://www.egroupware.org *
* Written by: *
* - Vinicius Cubas Brand <viniciuscb@users.sourceforge.net> *
* sponsored by Thyamad - http://www.thyamad.com *
* ------------------------------------------------------------------------- *
* Description: File version class handler for VFS (SQL implementation v2) *
* ------------------------------------------------------------------------- *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; either version 2 of the License, or (at your *
* option) any later version. *
\***************************************************************************/
class vfs_versionsystem
{
/* The high level database handler object */
// var $db_highlevel;
/* Stores the possible amount number of old file backups; In an
* inserction, this number will be verified and if there are already
* $backups backed up for a file, will delete backup of the oldest
* (although keeping the record of operations). 0 for no backup system
* and -1 to infinite versions. */
var $backups;
/* tmp dir (without end slash) to store temporary file backups (when
* file is snapshotted) */
var $tmp_dir;
/* Virtual file system base class */
var $vfs;
/* Stores information about snapshotted files. Array with the file_id
as index. */
var $snapshotted_files;
/* Database handling */
var $db;
/* Now */
var $now;
var $account_id;
var $last_saved_snapshot=-1;
var $backup_foldername = '_backup';
//Operations that create file backups
var $backup_operations = array(
VFS_OPERATION_EDITED
);
var $attributes = array(
'version_id', /* Integer. Unique to each modification. */
'file_id', /* Integer. Id of the file that modif. belongs.*/
'operation', /* Operation made in modification. */
'modifiedby_id', /* phpGW account_id of who last modified */
'modified', /* Datetime of modification, in SQL format */
'version', /* Version of file prior modification. */
'comment', /* Human-readable description of modification. */
'backup_file_id', /* file_id of file that is a backup . */
'backup_content', /* usable if files are stored in database. */
'src', /* source directory in a copy or move operation.*/
'dest' /* destination directory in a copy or move operation.*/
);
/*!
* @function vfs_versionsystem
* @abstract Object constructor
* @author Vinicius Cubas Brand
*/
function vfs_versionsystem($create_vfs=true)
{
//use create_vfs=false and after this use $this->set_vfs to keep the
// same object (i.e. use reference) in $this->vfs instead of
// creating a new object.
if ($create_vfs)
{
$this->vfs = CreateObject('phpgwapi.vfs');
}
/* FIXME this takes a value defined in the filescenter
* configuration. Better next time to take a value from global api
* configuration. must fix here and in the filescenter */
if (array_key_exists('filescenter',$GLOBALS['phpgw_info']['user']['preferences']))
{
$this->backups = $GLOBALS['phpgw_info']['user']['preferences']['filescenter']['vfs_backups'];
}
else
{
$this->backups = 5;
}
$this->snapshotted_files = array();
$this->db =& $GLOBALS['phpgw']->db;
$this->now = date('Y-m-d H:i:s');
$this->account_id = $GLOBALS['phpgw_info']['user']['account_id'];
$this->tmp_dir = $GLOBALS['phpgw_info']['server']['temp_dir'];
}
/*!
* @function create_initial_version()
* @abstract Creates a initial journal entry for a file
* @description Must be used after a file has been created. Will create
* an initial journal entry in the database. If somehow
* the database already have any journal for that file,
* this method is wrongly called and will do nothing.
* Also if no file is found with that file_id, fails.
*
* @author Vinicius Cubas Brand
*/
function create_initial_version($file_id)
{
if ($GLOBALS['phpgw']->banish_journal)
{
return;
}
$GLOBALS['phpgw']->banish_journal = true;
//See if file exists
$this->db->select('phpgw_vfs2_files','*',
array('file_id'=>$file_id), __LINE__,__FILE__);
if (!$this->db->next_record())
{
$GLOBALS['phpgw']->banish_journal = false;
return false;
}
$file_record = $this->db->Record;
//See if journal for the file already exists
$this->db->select('phpgw_vfs2_versioning','*',
array('file_id'=>$file_id),__LINE__,__FILE__);
if ($this->db->next_record())
{
$GLOBALS['phpgw']->banish_journal = false;
return true; //TODO error message
}
$insert_data = array(
'file_id' => $file_record['file_id'],
'operation' => VFS_OPERATION_CREATED,
'modified' => $this->now,
'modifiedby_id' => $this->account_id,
'version' => '0.0.0.0'
);
$res = $this->db->insert('phpgw_vfs2_versioning',$insert_data,null,
__LINE__,__FILE__);
if ($res)
{
$GLOBALS['phpgw']->banish_journal = false;
return true;
}
$GLOBALS['phpgw']->banish_journal = false;
return false;
}
/*!
* @function save_snapshot()
* @abstract Saves a snapshot from a file
* @description Must be called before any modification in a file. After
* the modification was successful, one must do a vfs_version->commit()
* Depending of the type of operation and how backups are set, will
* handle backups. If a commit is not made until the end of the script,
* no modifications in the journal will be saved.
*
* @param $file_id int The file_id
* @param $operation int A VFS_OPERATION as defined in vfs_shared file
* @param $other string Its use will differ depending on the operation:
* Copy,Move: $other contains the fake_full_path_clean of destination
*
* @author Vinicius Cubas Brand
* @result bool
*/
function save_snapshot($file_id,$operation,$comment='',$other='')
{
//Prevent recursive reentrant when working in vfs->copy, f.inst
if ($GLOBALS['phpgw']->banish_journal)
{
return;
}
$GLOBALS['phpgw']->banish_journal = true;
$this->db->select('phpgw_vfs2_files','*',
array('file_id'=>$file_id), __LINE__,__FILE__);
if (!$this->db->next_record())
{
$GLOBALS['phpgw']->banish_journal = false;
return false;
}
$file_record = $this->db->Record;
//If already snapshotted, will do a rollback in the old snapshot
//before make a new one.
if ($this->snapshotted_files[$file_record['file_id']])
{
$this->rollback($file_record['file_id']);
}
//Create a backup if necessary
if ($this->backups != 0 && in_array($operation,$this->backup_operations))
{
$random_filename = $this->tmp_dir.SEP.$this->random_filename();
$this->vfs->cp(array(
'from' => $file_record['directory'].SEP.$file_record['name'],
'to' => $random_filename,
'relatives' => array(RELATIVE_ROOT,RELATIVE_NONE|VFS_REAL)
));
$this->vfs->set_attributes(array(
'string' => $random_filename,
'relatives' => array(RELATIVE_NONE|VFS_REAL),
'attributes' => array('is_backup' => 'Y')
));
}
//backup_file_id and backup_data will be set in commit() only.
$insert_data = array(
'file_id' => $file_record['file_id'],
'operation' => $operation,
'modifiedby_id' => $this->account_id,
'modified' => $this->now, //Datetime of entry
'version' => $file_record['version'],
'comment' => $comment,
);
if ($operation == VFS_OPERATION_COPIED || $operation == VFS_OPERATION_MOVED)
{
$insert_data['src'] = $file_record['directory'].'/'.$file_record['name'];
$insert_data['dest'] = $other['dest'];
}
/* $file_data is the information of the file, stored in
* $this->snapshotted_files. 'insert_data' have the data to be
* inserted in the versioning table, 'tmp_filename' is the name of
* the temporary backup copy, if any, and 'record' is the
* information of the file before changes (that will be made between
* the call to save_snapshot() and the call to commit().
*/
$file_data = array(
'insert_data' => $insert_data,
'tmp_filename' => $random_filename,
'record' => $file_record
);
$this->snapshotted_files[$file_id] = $file_data;
$this->last_saved_snapshot = $file_id;
$GLOBALS['phpgw']->banish_journal = false;
return true;
}
/*!
* @function commit()
* @abstract Commits the creation of a journal entry
* @description Will have to be called after a save_snapshot is made.
* If a vfs_version->save_snapshot() call is not made before, this
* method does nothing. If no parameter is passed, will commit the
* file from the last saved snapshot.
*
* @param $file_id int The file_id
*
* @author Vinicius Cubas Brand
* @result bool
*/
function commit($file_id=-1)
{
//Prevent recursive reentrant when working in vfs->copy, f.inst
if ($GLOBALS['phpgw']->banish_journal)
{
return;
}
$GLOBALS['phpgw']->banish_journal = true;
if ($file_id == -1)
{
if ($this->last_saved_snapshot == -1)
{
$GLOBALS['phpgw']->banish_journal = false;
return false;
}
$file_id = $this->last_saved_snapshot;
}
if (!$this->snapshotted_files[$file_id])
{
$GLOBALS['phpgw']->banish_journal = false;
return false;
}
$file_data = $this->snapshotted_files[$file_id];
//if there is any backup to be made, will make these backups and
//remove too old backup versions, as defined in configuration.
if ($this->backups != 0 && in_array($file_data['insert_data']['operation'],$this->backup_operations))
{
//counts the number of stored backups
$where = "file_id=$file_id AND (backup_file_id != NULL OR backup_file_id != '')";
$this->db->select('phpgw_vfs2_versioning','count(*)',$where,
__LINE__,__FILE__);
$this->db->next_record();
if ($this->db->Record[0] >= $this->backups && $this->backups != -1)
{
//Remove old backups
//Deletes oldest backup(s)
$backups_to_be_deleted = $this->db->Record[0] - $this->backups + 1;
$sql = "SELECT vers.version_id as version_id,
vers.backup_file_id as backup_file_id,
files.directory as directory,
files.name as name
FROM phpgw_vfs2_versioning vers,
phpgw_vfs2_files files
WHERE vers.file_id=$file_id
AND vers.backup_file_id = files.file_id
ORDER BY vers.modified";
$this->db->query($sql,__LINE__,__FILE__);
for ($i = 0; $i < $backups_to_be_deleted; $i++)
{
//FIXME don't know why this only works 4 the 1st cycle
$this->db->next_record();
$version_file_id = $this->db->Record['backup_file_id'];
$version_id = $this->db->Record['version_id'];
$version_directory = $this->db->Record['directory'];
$version_name = $this->db->Record['name'];
//Removes old backup
$this->vfs->rm(array(
'string' => $version_directory.SEP.$version_name,
'relatives' => array(RELATIVE_ROOT)
));
$versions_to_update[] = $version_id;
}
if ($versions_to_update)
{
//updates old journal
$update_data = array(
'backup_file_id' => '',
'backup_content' => ''
);
foreach ($versions_to_update as $key => $val)
{
$update_where = array(
'version_id' => $val
);
$this->db->update('phpgw_vfs2_versioning',
$update_data,$update_where,__LINE__,__FILE__);
}
}
unset($version_id);
}
//create backup folder, if not exists
//Important: the backup dir will be inside the virtual root
$backup_foldername = $file_data['record']['directory'].SEP.$this->backup_foldername;
$dir = array(
'string' => $backup_foldername,
'relatives' => array(RELATIVE_ROOT)
);
if (!$this->vfs->file_exists($dir))
{
$this->vfs->mkdir($dir); //TODO error messages
$attributes=array_merge($dir,array(
'attributes' => array(
'is_backup' => 'Y'
)
));
$this->vfs->set_attributes($attributes);
}
//create a backup filename
$backup_filename = $this->backup_filename(
$file_data['record']['name'],
$file_data['insert_data']['version']
);
//move file from temporary location to its definitive location
$res = $this->vfs->mv(array(
'from' => $file_data['tmp_filename'],
'to' => $backup_foldername.SEP.$backup_filename,
'relatives' => array(RELATIVE_NONE|VFS_REAL,RELATIVE_ROOT)
));
//sets its attribute as backup
$this->vfs->set_attributes(array(
'string' => $backup_foldername.SEP.$backup_filename,
'relatives' => array(RELATIVE_ROOT),
'attributes' => array('is_backup' => 'Y')
));
//TODO backup content in database support
//Fetch the backup file_id to put this information in the
//version table
if ($res)
{
$res_ls = $this->vfs->ls(array(
'string' => $backup_foldername.SEP.$backup_filename,
'relatives' => RELATIVE_ROOT,
'nofiles' => True,
'backups' => True
));
if ($res_ls)
{
$file_data['insert_data']['backup_file_id'] = $res_ls[0]['file_id'];
}
}
}
$res = $this->db->insert('phpgw_vfs2_versioning',
$file_data['insert_data'],null,__LINE__,__FILE__);
if ($res)
{
//If operation is one of the type that increments file version
if (in_array($file_data['insert_data']['operation'],$this->backup_operations))
{
$this->db->update('phpgw_vfs2_files',
array('version' => $this->inc($file_data['insert_data']['version'])),
array('file_id' => $file_data['insert_data']['file_id']),
__LINE__, __FILE__
);
}
unset($this->snapshotted_files[$file_id]);
$this->last_saved_snapshot = -1;
$GLOBALS['phpgw']->banish_journal = false;
return true;
}
$GLOBALS['phpgw']->banish_journal = false;
return false;
}
/*!
* @function rollback()
* @abstract Rollbacks the save of the snapshot
* @description Will have to be called after a save_snapshot is made.
* If a vfs_version->save_snapshot() call is not made before, this
* method does nothing. If no parameter is passed, will rollback the
* file from the last saved snapshot. This method only deletes the
* temporary backup file and the saved file information
*
* @param $file_id int The file_id
*
* @author Vinicius Cubas Brand
* @result bool
*/
function rollback($file_id=-1)
{
//Prevent recursive reentrant when working in vfs->copy, f.inst
if ($GLOBALS['phpgw']->banish_journal)
{
return;
}
$GLOBALS['phpgw']->banish_journal = true;
if ($file_id == -1)
{
if ($this->last_saved_snapshot == -1)
{
$GLOBALS['phpgw']->banish_journal = false;
return false;
}
$file_id = $this->last_saved_snapshot;
}
if (!$this->snapshotted_files[$file_id])
{
$GLOBALS['phpgw']->banish_journal = false;
return false;
}
$file_data = $this->snapshotted_files[$file_id];
$this->vfs->rm(array(
'string' => $file_data['tmp_filename'],
'relatives' => array(RELATIVE_NONE | VFS_REAL)
));
unset($this->snapshotted_files[$file_id]);
$this->last_saved_snapshot = -1;
$GLOBALS['phpgw']->banish_journal = false;
return true;
}
/*!
* @function get_journal()
* @abstract Returns an array with the journal for a file
*/
function get_journal($file_id)
{
//TODO support for database-only storage.
$fields = array_diff($this->attributes,array('backup_content'));
$where = 'file_id='.$file_id.' ORDER BY modified DESC, version DESC, operation DESC';
$this->db->select('phpgw_vfs2_versioning',$fields,$where,
__LINE__,__FILE__);
while ($this->db->next_record())
{
$result[] = $this->db->Record;
}
return $result;
}
/*!
* @function inc()
* @abstract Given a file version, increments it using the vfs
* versioning pattern and returns the incremented file version.
* Analyzes operation and increments the file version taking
* consideration of this operation.
*
* @param $version string The file version
* @param $operation int Some VFS_OPERATION as defined in vfs_shared
*
* @result string
*/
function inc($version)
{
/*
* Let's increment the version for the file itself. We keep the
* current version when making the journal entry, because that was
* the version that was operated on. The maximum numbers for each
* part in the version string: none.99.9.9
*/
$version_parts = split ("\.", $version);
$newnumofparts = $numofparts = count ($version_parts);
if ($version_parts[3] >= 9)
{
$version_parts[3] = 0;
$version_parts[2]++;
$version_parts_3_update = 1;
}
elseif (isset ($version_parts[3]))
{
$version_parts[3]++;
}
if ($version_parts[2] >= 9 && $version_parts[3] == 0 && $version_parts_3_update)
{
$version_parts[2] = 0;
$version_parts[1]++;
}
if ($version_parts[1] > 99)
{
$version_parts[1] = 0;
$version_parts[0]++;
}
for ($i = 0; $i < $newnumofparts; $i++)
{
if (!isset ($version_parts[$i]))
{
break;
}
if ($i)
{
$newversion .= '.';
}
$newversion .= $version_parts[$i];
}
return $newversion;
}
function set_vfs(&$vfs)
{
$this->vfs =& $vfs;
}
#helper, private functions
/*!
* @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 backup_filename()
* @abstract Return the backup filename for a certain filename + version
*
* @result string
*/
function backup_filename($filename,$version)
{
$version = str_replace('.','_',$version);
$fbrk = explode('.',$filename);
$fbrk[0] .= '-'.$version;
return implode('.',$fbrk);
}
}
?>