1<?php
2/**
3 * EGroupware - Filemanager - select file to open or save dialog
4 *
5 * @link http://www.egroupware.org
6 * @package filemanager
7 * @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
8 * @copyright (c) 2009-2016 by Ralf Becker <RalfBecker-AT-outdoor-training.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\Link;
15use EGroupware\Api\Framework;
16use EGroupware\Api\Egw;
17use EGroupware\Api\Vfs;
18use EGroupware\Api\Etemplate;
19
20/**
21 * Select file to open or save dialog
22 *
23 * This dialog can be called from applications to open or store files from the VFS.
24 *
25 * There are the following ($_GET) parameters:
26 * - menuaction=filemanager.filemanager_select.select   (required)
27 * - mode=(open|open-multiple|saveas|select-dir)        (required)
28 * - method=app.class.method                            (required callback, gets called with id and selected file(s))
29 * - id=...                                             (optional parameter passed to callback)
30 * - path=...                                           (optional start path in VFS)
31 * - mime=...                                           (optional mime-type to limit display to given type)
32 * - label=...                                          (optional label for submit button, default "Open")
33 *
34 * The application calls this method in a popup with size: 640x580 px
35 * After the user selected one or more files (depending on the mode parameter), the "method" callback gets
36 * called on server (!) side. Parameters are the id plus the selected files as 1. and 2. parameter.
37 * The callback returns javascript to eg. update it's UI AND (!) to close the current popup ("window.close();").
38 *
39 * @deprecated This class is deprecated in favor of et2_vfsSelect widget. Please
40 * use et2_vfsSelect widget if you are not running old etemplate.
41 *
42 * @todo this class should be removed once we have all applications ported in et2
43 */
44class filemanager_select
45{
46	/**
47	 * Methods callable via menuaction
48	 *
49	 * @var array
50	 */
51	var $public_functions = array(
52		'select' => true,
53	);
54
55	/**
56	 * Constructor
57	 *
58	 */
59	function __construct()
60	{
61		// strip slashes from _GET parameters, if someone still has magic_quotes_gpc on
62		if (get_magic_quotes_gpc() && $_GET)
63		{
64			$_GET = array_stripslashes($_GET);
65		}
66	}
67
68	/**
69	 * File selector
70	 *
71	 * @param array $content
72	 *
73	 * @deprecated Please use et2_vfsSelect widget in client side instead
74	 */
75	function select(array $content=null)
76	{
77		if (!is_array($content))
78		{
79			$content = array();
80			$content['mode'] = $_GET['mode'];
81			if (!in_array($content['mode'],array('open','open-multiple','saveas','select-dir')))
82			{
83				throw new Api\Exception\WrongParameter("Wrong or unset required mode parameter!");
84			}
85			$content['path'] = $_GET['path'];
86			if (empty($content['path']))
87			{
88				$content['path'] = Api\Cache::getSession('filemanger', 'select_path');
89			}
90			$content['name'] = (string)$_GET['name'];
91			$content['method'] = $_GET['method'];
92			$content['id']     = $_GET['id'];
93			$content['label'] = isset($_GET['label']) ? $_GET['label'] : lang('Open');
94			if (($content['options-mime'] = isset($_GET['mime'])))
95			{
96				$sel_options['mime'] = array();
97				foreach((array)$_GET['mime'] as $key => $value)
98				{
99					if (is_numeric($key))
100					{
101						$sel_options['mime'][$value] = lang('%1 files',strtoupper(Api\MimeMagic::mime2ext($value))).' ('.$value.')';
102					}
103					else
104					{
105						$sel_options['mime'][$key] = lang('%1 files',strtoupper($value)).' ('.$key.')';
106					}
107				}
108
109				$content['mime'] = key($sel_options['mime']);
110				error_log(array2string($content['options-mime']));
111			}
112		}
113		elseif(isset($content['button']))
114		{
115			$button = key($content['button']);
116			unset($content['button']);
117			switch($button)
118			{
119				case 'home':
120					$content['path'] = filemanager_ui::get_home_dir();
121					break;
122				case 'ok':
123					$copy_result = null;
124					if (isset($content['file_upload']['name']) && file_exists($content['file_upload']['tmp_name']))
125					{
126						//Set the "content" name filed accordingly to the uploaded file
127						// encode chars which special meaning in url/vfs (some like / get removed!)
128						$content['name'] = Vfs::encodePathComponent($content['file_upload']['name']);
129						$to_path = Vfs::concat($content['path'],$content['name']);
130
131						$copy_result = (Vfs::is_writable($content['path']) || Vfs::is_writable($to_path)) &&
132							copy($content['file_upload']['tmp_name'],Vfs::PREFIX.$to_path);
133					}
134
135					//Break on an error condition
136					if ((($content['mode'] == 'open' || $content['mode'] == 'saveas') && ($content['name'] == '')) || ($copy_result === false))
137					{
138						if ($copy_result === false)
139						{
140							$content['msg'] = lang('Error uploading file!');
141						}
142						else
143						{
144							$content['msg'] = lang('Filename must not be empty!');
145						}
146						$content['name'] = '';
147
148						break;
149					}
150
151					switch($content['mode'])
152					{
153						case 'open-multiple':
154							foreach((array)$content['dir']['selected'] as $name)
155							{
156								$files[] = Vfs::concat($content['path'],$name);
157							}
158							//Add an uploaded file to the files result array2string
159							if ($copy_result === true) $files[] = $to_path;
160							break;
161
162						case 'select-dir':
163							$files = $content['path'];
164							break;
165
166						case 'saveas':
167							// Don't trust the name the user gives, encode it
168							$content['name'] = Vfs::encodePathComponent($content['name']);
169							// Fall through
170
171						default:
172							$files = Vfs::concat($content['path'],$content['name']);
173							break;
174					}
175
176					if ($content['method'] == 'download_url' && !is_array($files))
177					{
178							$files =  Vfs::download_url($files);
179							if ($files[0] == '/') $files = Egw::link($files);
180					}
181					else
182					{
183						$js = ExecMethod2($content['method'],$content['id'],$files);
184					}
185
186					if(Api\Json\Response::isJSONResponse())
187					{
188						$response = Api\Json\Response::get();
189						if($js)
190						{
191							$response->script($js);
192						}
193						// Ahh!
194						// The vfs-select widget looks for this
195						$response->script('this.selected_files = '.json_encode($files) . ';');
196						Framework::window_close();
197					}
198					else
199					{
200						header('Content-type: text/html; charset='.Api\Translation::charset());
201						echo "<html>\n<head>\n<script type='text/javascript'>\n$js\n</script>\n</head>\n</html>\n";
202					}
203					exit();
204			}
205
206			$sel_options['mime'] = $content['options-mime'];
207		}
208		elseif(isset($content['apps']))
209		{
210			$app = key($content['apps']);
211			if ($app == 'home') $content['path'] = filemanager_ui::get_home_dir();
212		}
213
214		//Deactivate the opload field if the current directory is not writeable or
215		//we're currently not in the single file open mode.
216		$content['no_upload'] = !Vfs::is_writable($content['path']) ||
217			!in_array($content['mode'],array('open'));
218
219		$content['apps'] = array_keys(self::get_apps());
220
221		if (isset($app))
222		{
223			$content['path'] = '/apps/'.(isset($content['apps'][$app]) ? $content['apps'][$app] : $app);
224		}
225
226		// Set a flag for easy detection as we go
227		$favorites_flag = substr($content['path'],0,strlen('/apps/favorites')) == '/apps/favorites';
228
229		if (!$favorites_flag && (!$content['path'] || !Vfs::is_dir($content['path'])))
230		{
231			$content['path'] = filemanager_ui::get_home_dir();
232		}
233		$tpl = new Etemplate('filemanager.select');
234
235		if ($favorites_flag)
236		{
237			// Display favorites as if they were folders
238			$files = array();
239			$favorites = Framework\Favorites::get_favorites('filemanager');
240			$n = 0;
241			foreach($favorites as $favorite)
242			{
243				$path = $favorite['state']['path'];
244				// Just directories
245				if(!$path) continue;
246				if ($path == $content['path']) continue;	// remove directory itself
247
248				$mime = Vfs::mime_content_type($path);
249				$content['dir'][$n] = array(
250					'name' => $favorite['name'],
251					'path' => $path,
252					'mime' => $mime,
253					'is_dir' => true
254				);
255				if ($content['mode'] == 'open-multiple')
256				{
257					$readonlys['selected['.$favorite['name'].']'] = true;
258				}
259				++$n;
260			}
261		}
262		else if (!($files = Vfs::find($content['path'],array(
263			'dirsontop' => true,
264			'order' => 'name',
265			'sort' => 'ASC',
266			'maxdepth' => 1,
267		))))
268		{
269			$content['msg'] = lang("Can't open directory %1!",$content['path']);
270		}
271		else
272		{
273			$n = 0;
274			$content['dir'] = array('mode' => $content['mode']);
275			foreach($files as $path)
276			{
277				if ($path == $content['path']) continue;	// remove directory itself
278
279				$name = Vfs::basename($path);
280				$is_dir = Vfs::is_dir($path);
281				$mime = Vfs::mime_content_type($path);
282				if ($content['mime'] && !$is_dir && $mime != $content['mime'])
283				{
284					continue;	// does not match mime-filter --> ignore
285				}
286				$content['dir'][$n] = array(
287					'name' => $name,
288					'path' => $path,
289					'mime' => $mime,
290					'is_dir' => $is_dir
291				);
292				if ($is_dir && $content['mode'] == 'open-multiple')
293				{
294					$readonlys['selected['.$name.']'] = true;
295				}
296				++$n;
297			}
298			if (!$n) $readonlys['selected[]'] = true;	// remove checkbox from empty line
299		}
300		$readonlys['button[createdir]'] = !Vfs::is_writable($content['path']);
301
302		//_debug_array($readonlys);
303		Api\Cache::setSession('filemanger', 'select_path', $content['path']);
304		$preserve = array(
305			'mode'   => $content['mode'],
306			'method' => $content['method'],
307			'id'     => $content['id'],
308			'label'  => $content['label'],
309			'mime'   => $content['mime'],
310			'options-mime' => $sel_options['mime'],
311			'old_path' => $content['path'],
312		);
313		$tpl->exec('filemanager.filemanager_select.select',$content,$sel_options,$readonlys,$preserve,2);
314	}
315
316	/**
317	 * Get a list off all apps having an application directory in VFS
318	 *
319	 * @return array
320	 */
321	static function get_apps()
322	{
323		$apps = array(false);	// index starting from 1
324		if (isset($GLOBALS['egw_info']['apps']['stylite'])) $apps = array('favorites' => lang('Favorites'));
325		$apps += Link::app_list('query');
326
327		unset($apps['mydms']);	// they do NOT support adding files to VFS
328		unset($apps['wiki']);
329		unset($apps['api-accounts']);
330		unset($apps['addressbook-email']);
331
332		return $apps;
333	}
334}
335