1<?php
2/**
3 * EGroupware Filemanager: shares
4 *
5 * @link http://www.egroupware.org/
6 * @package filemanager
7 * @author Ralf Becker <rb-AT-stylite.de>
8 * @copyright (c) 2014-16 by Ralf Becker <rb-AT-stylite.de>
9 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
10 * @version $Id$
11 */
12
13use EGroupware\Api;
14use EGroupware\Api\Framework;
15use EGroupware\Api\Etemplate;
16use EGroupware\Api\Vfs\Sharing;
17
18/**
19 * Filemanager: shares
20 */
21class filemanager_shares extends filemanager_ui
22{
23	/**
24	 * Functions callable via menuaction
25	 *
26	 * @var array
27	 */
28	public $public_functions = array(
29		'index' => true,
30	);
31
32	/**
33	 * Autheticated user is setup config user
34	 *
35	 * @var boolean
36	 */
37	static protected $is_setup = false;
38
39	static protected $tmp_dir;
40
41	/**
42	 * Constructor
43	 */
44	function __construct()
45	{
46		// sudo handling
47		parent::__construct();
48		self::$is_setup = Api\Cache::getSession('filemanager', 'is_setup');
49		self::$tmp_dir = '/home/'.$GLOBALS['egw_info']['user']['account_lid'].'/.tmp/';
50	}
51
52	/**
53	 * Callback to fetch the rows for the nextmatch widget
54	 *
55	 * @param array $query with keys 'start', 'search', 'order', 'sort', 'col_filter'
56	 *	For other keys like 'filter', 'cat_id' you have to reimplement this method in a derived class.
57	 * @param array &$rows returned rows/competitions
58	 * @param array &$readonlys eg. to disable buttons based on acl, not use here, maybe in a derived class
59	 * @return int total number of rows
60	 */
61	public function get_rows($query, &$rows)
62	{
63		switch ($query['col_filter']['type'])
64		{
65			case Sharing::LINK:
66				$query['col_filter'][] = "share_path LIKE ".$GLOBALS['egw']->db->quote(self::$tmp_dir.'%');
67				break;
68
69			case Sharing::READONLY:
70				$query['col_filter'][] = "share_path NOT LIKE ".$GLOBALS['egw']->db->quote(self::$tmp_dir.'%');
71				$query['col_filter']['share_writable'] = false;
72				break;
73
74			case Sharing::WRITABLE:
75				$query['col_filter']['share_writable'] = true;
76				break;
77		}
78		unset($query['col_filter']['type']);
79
80		if (class_exists('EGroupware\\Collabora\\Wopi'))
81		{
82			$query['col_filter'][] = 'share_writable NOT IN ('.
83				EGroupware\Collabora\Wopi::WOPI_WRITABLE.','.EGroupware\Collabora\Wopi::WOPI_READONLY.')';
84		}
85
86		if ((string)$query['col_filter']['share_passwd'] !== '')
87		{
88			$query['col_filter'][] = $query['col_filter']['share_passwd'] === 'yes' ?
89				'share_passwd IS NOT NULL' : 'share_passwd IS NULL';
90		}
91		unset($query['col_filter']['share_passwd']);
92
93		$query['col_filter']['share_owner'] = $GLOBALS['egw_info']['user']['account_id'];
94
95		$readonlys = null;
96		$total = Sharing::so()->get_rows($query, $rows, $readonlys);
97
98		foreach($rows as &$row)
99		{
100			if (substr($row['share_path'], 0, strlen(self::$tmp_dir)) === self::$tmp_dir)
101			{
102				$row['share_path'] = substr($row['share_path'], strlen(self::$tmp_dir));
103				$row['type'] = Sharing::LINK;
104			}
105			else
106			{
107				$row['type'] = $row['share_writable'] ? Sharing::WRITABLE : Sharing::READONLY;
108			}
109			$row['share_passwd'] = (boolean)$row['share_passwd'];
110			if ($row['share_with']) $row['share_with'] = preg_replace('/,([^ ])/', ', $1', $row['share_with']);
111
112			foreach(['share_created','share_last_accessed'] as $date_field)
113			{
114				$row[$date_field] = Api\DateTime::server2user($row[$date_field]);
115			}
116		}
117		return $total;
118	}
119
120	/**
121	 * Context menu
122	 *
123	 * @return array
124	 */
125	public static function get_actions()
126	{
127		$group = 1;
128		$actions = array(
129
130			'shareLink' => array(
131				'caption' => lang('View link'),
132				'group' => $group,
133				'icon' => 'share',
134				'allowOnMultiple' => false,
135				'default' => true,
136				'onExecute' => 'javaScript:app.filemanager.view_link',
137				'disableIfNoEPL' => true
138			),
139			'shareEdit' => array(
140				'caption' => lang('Edit Share'),
141				'group' => 1,
142				'icon' => 'edit',
143				'allowOnMultiple' => false,
144				'popup' => '500x200',
145				'url' => 'menuaction=stylite.stylite_filemanager.edit_share&share_id=$id',
146				'disableIfNoEPL' => true
147			),
148			'delete' => array(
149				'caption' => lang('Delete'),
150				'group' => ++$group,
151				'confirm' => 'Delete these shares?',
152			),
153		);
154		return $actions;
155	}
156
157	/**
158	 * Show files shared
159	 *
160	 * @param array $content=null
161	 * @param string $msg=''
162	 */
163	public function index(array $content=null)
164	{
165		if (!is_array($content))
166		{
167			$content = array(
168				'nm' => array(
169					'get_rows'       =>	'filemanager.filemanager_shares.get_rows',	// I  method/callback to request the data for the rows eg. 'notes.bo.get_rows'
170					'no_filter'      => True,	// current dir only
171					'no_filter2'     => True,	// I  disable the 2. filter (params are the same as for filter)
172					'no_cat'         => True,	// I  disable the cat-selectbox
173					'lettersearch'   => false,	// I  show a lettersearch
174					'searchletter'   =>	false,	// I0 active letter of the lettersearch or false for [all]
175					'start'          =>	0,		// IO position in list
176					'order'          =>	'share_created',	// IO name of the column to sort after (optional for the sortheaders)
177					'sort'           =>	'DESC',	// IO direction of the sort: 'ASC' or 'DESC'
178					//'default_cols'   => '!',	// I  columns to use if there's no user or default pref (! as first char uses all but the named columns), default all columns
179					'csv_fields'     =>	false, // I  false=disable csv export, true or unset=enable it with auto-detected fieldnames,
180									//or array with name=>label or name=>array('label'=>label,'type'=>type) pairs (type is a eT widget-type)
181					'actions'        => self::get_actions(),
182					'row_id'         => 'share_id',
183					'dataStorePrefix' => 'egw_shares',
184				),
185			);
186		}
187		elseif ($content['nm']['action'])
188		{
189			switch($content['nm']['action'])
190			{
191				case 'delete':
192					$where = array('share_owner' => $GLOBALS['egw_info']['user']['account_id']);
193					if (!$content['nm']['select_all'])
194					{
195						$where['share_id'] = $content['nm']['selected'];
196					}
197					Framework::message(lang('%1 shares deleted.', Sharing::delete($where)), 'success');
198					break;
199				default:
200					throw new Api\Exception\WrongParameter("Unknown action '{$content['nm']['action']}'!");
201			}
202			unset($content['nm']['action']);
203			unset($content['nm']['id']);
204		}
205		$content['is_setup'] = self::$is_setup;
206
207		$sel_options = array(
208			'type' => Sharing::$modes,
209			'share_passwd' => array(
210				'no' => lang('No'),
211				'yes' => lang('Yes'),
212			)
213		);
214		unset($sel_options['type'][Sharing::ATTACH]);
215
216		$tpl = new Etemplate('filemanager.shares');
217		$tpl->exec('filemanager.filemanager_shares.index', $content, $sel_options, null, $content);
218	}
219}